-- BizMatch Phase 2 — initial schema
-- Matches the agreed data model (Buyer / Contact / NDA / Deal / Business
-- / Note / Todo / Document / ExtractionJob / Staff)

CREATE OR REPLACE FUNCTION set_updated_at() RETURNS trigger AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- ---------------------------------------------------------------- staff
CREATE TABLE staff (
  id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  name       text NOT NULL UNIQUE,
  active     boolean NOT NULL DEFAULT true,
  created_at timestamptz NOT NULL DEFAULT now()
);

-- ------------------------------------------------------------- business
CREATE TABLE business (
  id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  name       text NOT NULL,
  nas_path   text NOT NULL UNIQUE,
  status     text NOT NULL CHECK (status IN ('ACTIVE', 'SOLD', 'INACTIVE')),
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX business_status_idx ON business (status);
CREATE TRIGGER business_updated BEFORE UPDATE ON business
  FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ---------------------------------------------------------------- buyer
CREATE TABLE buyer (
  id           uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  company_name text,
  status       text NOT NULL DEFAULT 'ACTIVE'
               CHECK (status IN ('ACTIVE', 'DEACTIVATED', 'LEGACY')),
  legacy_json  jsonb,
  created_by   uuid REFERENCES staff (id),
  created_at   timestamptz NOT NULL DEFAULT now(),
  updated_at   timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX buyer_status_idx ON buyer (status);
CREATE TRIGGER buyer_updated BEFORE UPDATE ON buyer
  FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- -------------------------------------------------------------- contact
CREATE TABLE contact (
  id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  buyer_id   uuid NOT NULL REFERENCES buyer (id) ON DELETE CASCADE,
  name       text NOT NULL,
  email      text,
  phone      text,
  is_primary boolean NOT NULL DEFAULT false,
  created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX contact_buyer_idx ON contact (buyer_id);
-- Dedup anchor: normalized e-mail
CREATE INDEX contact_email_idx ON contact (lower(btrim(email))) WHERE email IS NOT NULL;

-- ------------------------------------------------------------------ nda
-- One "request round": for every new request the buyer fills in a new NDA.
CREATE TABLE nda (
  id                        uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  buyer_id                  uuid NOT NULL REFERENCES buyer (id) ON DELETE CASCADE,
  status                    text NOT NULL DEFAULT 'SENT'
                            CHECK (status IN ('SENT', 'SIGNED')),
  nas_path                  text,
  sent_at                   date,
  signed_at                 date,
  preferred_businesses_text text,
  created_by                uuid REFERENCES staff (id),
  created_at                timestamptz NOT NULL DEFAULT now(),
  updated_at                timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX nda_buyer_idx ON nda (buyer_id);
CREATE INDEX nda_open_idx ON nda (sent_at) WHERE status = 'SENT';
CREATE TRIGGER nda_updated BEFORE UPDATE ON nda
  FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ----------------------------------------------------------------- deal
-- Relation buyer <-> business within one NDA round.
-- Deliberately NO unique constraint on (buyer_id, business_id):
-- a new NDA round => a new deal, the history stays visible.
CREATE TABLE deal (
  id           uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  buyer_id     uuid NOT NULL REFERENCES buyer (id) ON DELETE CASCADE,
  business_id  uuid NOT NULL REFERENCES business (id),
  nda_id       uuid REFERENCES nda (id),
  status       text NOT NULL DEFAULT 'NEW'
               CHECK (status IN ('NEW', 'INFO_SENT', 'DUE_DILIGENCE',
                                 'LOI', 'CLOSING', 'ENDED')),
  follow_up_at date,
  created_by   uuid REFERENCES staff (id),
  created_at   timestamptz NOT NULL DEFAULT now(),
  updated_at   timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX deal_buyer_idx ON deal (buyer_id);
CREATE INDEX deal_business_idx ON deal (business_id);
CREATE INDEX deal_status_idx ON deal (status);
CREATE INDEX deal_follow_up_idx ON deal (follow_up_at)
  WHERE follow_up_at IS NOT NULL AND status <> 'ENDED';
CREATE TRIGGER deal_updated BEFORE UPDATE ON deal
  FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ------------------------------------------------------------- document
-- Pure NAS reference; the NAS stays the source of truth.
CREATE TABLE document (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  nas_path    text NOT NULL,
  kind        text NOT NULL DEFAULT 'OTHER'
              CHECK (kind IN ('NDA', 'OVERVIEW', 'SUMMARY',
                              'SELLER_AGREEMENT', 'LOI', 'OTHER')),
  buyer_id    uuid REFERENCES buyer (id) ON DELETE CASCADE,
  business_id uuid REFERENCES business (id) ON DELETE CASCADE,
  deal_id     uuid REFERENCES deal (id) ON DELETE CASCADE,
  added_by    uuid REFERENCES staff (id),
  added_at    timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT document_has_ref CHECK (
    num_nonnulls(buyer_id, business_id, deal_id) >= 1
  )
);
CREATE INDEX document_buyer_idx ON document (buyer_id) WHERE buyer_id IS NOT NULL;
CREATE INDEX document_business_idx ON document (business_id) WHERE business_id IS NOT NULL;
CREATE INDEX document_deal_idx ON document (deal_id) WHERE deal_id IS NOT NULL;

-- ----------------------------------------------------------------- note
-- Attached to exactly ONE reference object (buyer, deal, business or NDA).
CREATE TABLE note (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  text        text NOT NULL,
  highlight   boolean NOT NULL DEFAULT false,
  buyer_id    uuid REFERENCES buyer (id) ON DELETE CASCADE,
  deal_id     uuid REFERENCES deal (id) ON DELETE CASCADE,
  business_id uuid REFERENCES business (id) ON DELETE CASCADE,
  nda_id      uuid REFERENCES nda (id) ON DELETE CASCADE,
  created_by  uuid NOT NULL REFERENCES staff (id),
  created_at  timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT note_exactly_one_ref CHECK (
    num_nonnulls(buyer_id, deal_id, business_id, nda_id) = 1
  )
);
CREATE INDEX note_buyer_idx ON note (buyer_id) WHERE buyer_id IS NOT NULL;
CREATE INDEX note_deal_idx ON note (deal_id) WHERE deal_id IS NOT NULL;
CREATE INDEX note_business_idx ON note (business_id) WHERE business_id IS NOT NULL;
CREATE INDEX note_nda_idx ON note (nda_id) WHERE nda_id IS NOT NULL;

-- ----------------------------------------------------------------- todo
-- kind TASK = normal task, REVIEW = request for proofreading/approval (with document_id).
-- At most ONE case reference; no reference at all is allowed (general task).
CREATE TABLE todo (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  text        text NOT NULL,
  kind        text NOT NULL DEFAULT 'TASK' CHECK (kind IN ('TASK', 'REVIEW')),
  assigned_to uuid NOT NULL REFERENCES staff (id),
  due_at      date,
  status      text NOT NULL DEFAULT 'OPEN' CHECK (status IN ('OPEN', 'DONE')),
  done_by     uuid REFERENCES staff (id),
  done_at     timestamptz,
  buyer_id    uuid REFERENCES buyer (id) ON DELETE CASCADE,
  deal_id     uuid REFERENCES deal (id) ON DELETE CASCADE,
  business_id uuid REFERENCES business (id) ON DELETE CASCADE,
  nda_id      uuid REFERENCES nda (id) ON DELETE CASCADE,
  document_id uuid REFERENCES document (id) ON DELETE SET NULL,
  created_by  uuid NOT NULL REFERENCES staff (id),
  created_at  timestamptz NOT NULL DEFAULT now(),
  updated_at  timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT todo_max_one_ref CHECK (
    num_nonnulls(buyer_id, deal_id, business_id, nda_id) <= 1
  )
);
CREATE INDEX todo_assignee_idx ON todo (assigned_to, status);
CREATE INDEX todo_due_idx ON todo (due_at) WHERE status = 'OPEN';
CREATE TRIGGER todo_updated BEFORE UPDATE ON todo
  FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ------------------------------------------------------- extraction_job
-- Queue for the asynchronous NDA extraction via vision_runner (worker polls QUEUED).
CREATE TABLE extraction_job (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  nda_id      uuid NOT NULL REFERENCES nda (id) ON DELETE CASCADE,
  status      text NOT NULL DEFAULT 'QUEUED'
              CHECK (status IN ('QUEUED', 'RUNNING', 'DONE', 'FAILED')),
  attempts    integer NOT NULL DEFAULT 0,
  result_json jsonb,
  error       text,
  created_at  timestamptz NOT NULL DEFAULT now(),
  started_at  timestamptz,
  finished_at timestamptz,
  reviewed_by uuid REFERENCES staff (id),
  reviewed_at timestamptz
);
CREATE INDEX extraction_job_queue_idx ON extraction_job (created_at)
  WHERE status = 'QUEUED';
CREATE INDEX extraction_job_nda_idx ON extraction_job (nda_id);
