INSERT INTO osint.exhibit_types (id,name) VALUES ('party','Party');

CREATE TABLE osint.party_exhibits (
  exhibit_id UUID PRIMARY KEY REFERENCES osint.exhibits(id) ON DELETE CASCADE,
  party_kind TEXT NOT NULL CHECK (party_kind IN ('person','organization')),
  display_name TEXT NOT NULL,
  summary TEXT NOT NULL DEFAULT ''
);

CREATE TABLE osint.person_parties (
  exhibit_id UUID PRIMARY KEY REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  given_name TEXT,
  family_name TEXT
);

CREATE TABLE osint.organization_parties (
  exhibit_id UUID PRIMARY KEY REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  organization_kind TEXT NOT NULL DEFAULT 'business'
    CHECK (organization_kind IN ('business','public_body','association','informal_group','other'))
);

CREATE TABLE osint.party_aliases (
  id UUID PRIMARY KEY,
  party_exhibit_id UUID NOT NULL REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  alias TEXT NOT NULL,
  sort_order INTEGER NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
  UNIQUE (party_exhibit_id,alias)
);

CREATE TABLE osint.party_evidence (
  board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
  party_exhibit_id UUID NOT NULL REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  evidence_exhibit_id UUID NOT NULL REFERENCES osint.exhibits(id) ON DELETE CASCADE,
  sort_order INTEGER NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
  note TEXT,
  PRIMARY KEY (party_exhibit_id,evidence_exhibit_id),
  CHECK (party_exhibit_id <> evidence_exhibit_id),
  FOREIGN KEY (board_id,party_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE,
  FOREIGN KEY (board_id,evidence_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE
);

CREATE TABLE osint.party_relationship_types (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL UNIQUE,
  directed BOOLEAN NOT NULL DEFAULT TRUE
);
INSERT INTO osint.party_relationship_types (id,name,directed) VALUES
  ('employment','Employment',TRUE), ('ownership','Ownership',TRUE),
  ('membership','Membership',TRUE), ('control','Control',TRUE),
  ('representation','Representation',TRUE), ('associated','Associated',FALSE);

CREATE TABLE osint.party_relationships (
  id UUID PRIMARY KEY,
  board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
  relationship_type_id TEXT NOT NULL REFERENCES osint.party_relationship_types(id),
  from_party_exhibit_id UUID NOT NULL REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  to_party_exhibit_id UUID NOT NULL REFERENCES osint.party_exhibits(exhibit_id) ON DELETE CASCADE,
  note TEXT,
  CHECK (from_party_exhibit_id <> to_party_exhibit_id),
  FOREIGN KEY (board_id,from_party_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE,
  FOREIGN KEY (board_id,to_party_exhibit_id) REFERENCES osint.exhibits(board_id,id) ON DELETE CASCADE
);

CREATE TABLE osint.level_briefs (
  board_id UUID PRIMARY KEY REFERENCES osint.boards(id) ON DELETE CASCADE,
  body TEXT NOT NULL DEFAULT ''
);

CREATE TABLE osint.brief_concepts (
  id UUID PRIMARY KEY,
  board_id UUID NOT NULL REFERENCES osint.boards(id) ON DELETE CASCADE,
  origin_concept_id UUID REFERENCES osint.brief_concepts(id) ON DELETE SET NULL,
  label TEXT NOT NULL,
  context_text TEXT NOT NULL DEFAULT '',
  sort_order INTEGER NOT NULL DEFAULT 0 CHECK (sort_order >= 0),
  expected_party_kind TEXT CHECK (expected_party_kind IN ('person','organization')),
  resolved_party_exhibit_id UUID REFERENCES osint.party_exhibits(exhibit_id) ON DELETE SET NULL,
  UNIQUE (board_id,label),
  FOREIGN KEY (board_id,resolved_party_exhibit_id) REFERENCES osint.exhibits(board_id,id)
);

COMMENT ON TABLE osint.brief_concepts IS 'Named concepts in the level brief which may be classified into Party exhibits by the investigator.';
COMMENT ON COLUMN osint.brief_concepts.expected_party_kind IS 'Author-only expected classification; omitted from play-mode API projections.';
