-- Initiative Recognition System — PostgreSQL schema (architecture_plan.md §4)
-- Table order respects FKs (units before users).

CREATE EXTENSION IF NOT EXISTS citext;

-- =========  ENUMS  =========
DO $$ BEGIN
  CREATE TYPE user_role AS ENUM ('applicant','council_member','editor','admin','viewer');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE initiative_class AS ENUM ('technical','research','textbook');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE research_evidence AS ENUM ('international','domestic','poster');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE eval_level AS ENUM ('high','medium','low');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE submission_status AS ENUM ('draft','submitted','under_review','approved','rejected');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE recognition_tier AS ENUM ('excellent','good');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- =========  IDENTITY  =========
CREATE TABLE IF NOT EXISTS units (
  id        UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name      TEXT NOT NULL,
  parent_id UUID REFERENCES units(id),
  address   TEXT
);

CREATE TABLE IF NOT EXISTS users (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email           CITEXT UNIQUE NOT NULL,
  password_hash   TEXT NOT NULL,
  full_name       TEXT NOT NULL,
  phone           TEXT,
  unit_id         UUID REFERENCES units(id),
  is_active       BOOLEAN NOT NULL DEFAULT TRUE,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS user_roles (
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  role    user_role NOT NULL,
  PRIMARY KEY (user_id, role)
);

-- System user for anonymous draft saves (no login yet)
INSERT INTO users (id, email, password_hash, full_name)
VALUES (
  '00000000-0000-4000-8000-000000000001',
  'system@draft.local',
  '-',
  'System (draft owner)'
)
ON CONFLICT (email) DO NOTHING;

-- =========  CASE / INITIATIVE ROOT  =========
CREATE TABLE IF NOT EXISTS initiatives (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  case_code       TEXT UNIQUE NOT NULL,
  owner_id        UUID NOT NULL REFERENCES users(id),
  status          submission_status NOT NULL DEFAULT 'draft',
  recognition_tier recognition_tier,
  submitted_at    TIMESTAMPTZ,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_initiatives_owner_status ON initiatives(owner_id, status);

-- =========  DRAFT SNAPSHOTS  =========
CREATE TABLE IF NOT EXISTS drafts (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  draft_code      TEXT UNIQUE NOT NULL,
  initiative_id   UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  payload         JSONB NOT NULL,
  version         INTEGER NOT NULL DEFAULT 1,
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_drafts_initiative ON drafts(initiative_id);

-- =========  ĐƠN (APPLICATION)  =========
CREATE TABLE IF NOT EXISTS applications (
  initiative_id              UUID PRIMARY KEY REFERENCES initiatives(id) ON DELETE CASCADE,
  initiative_name            TEXT NOT NULL,
  investor_name              TEXT,
  application_field          TEXT,
  first_apply_date           DATE,
  initiative_classification  initiative_class,
  research_evidence_kind     research_evidence,
  international_journal_decl TEXT,
  content_summary            TEXT,
  confidential_info          TEXT,
  conditions                 TEXT,
  author_evaluation          TEXT,
  trial_evaluation           TEXT,
  submission_day             SMALLINT,
  submission_month           SMALLINT,
  submission_year            SMALLINT,
  honesty_confirmed          BOOLEAN NOT NULL DEFAULT FALSE,
  CONSTRAINT chk_first_apply_window
     CHECK (first_apply_date IS NULL
            OR first_apply_date BETWEEN DATE '2025-04-15' AND DATE '2026-04-15')
);

CREATE TABLE IF NOT EXISTS authors (
  id                   UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id        UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  user_id              UUID REFERENCES users(id),
  ordinal              SMALLINT NOT NULL,
  full_name            TEXT NOT NULL,
  dob                  DATE,
  workplace            TEXT,
  title                TEXT,
  qualification        TEXT,
  contribution_percent NUMERIC(5,2) NOT NULL,
  is_representative    BOOLEAN NOT NULL DEFAULT FALSE,
  CHECK (contribution_percent >= 0 AND contribution_percent <= 100)
);
CREATE UNIQUE INDEX IF NOT EXISTS uq_authors_repr ON authors(initiative_id) WHERE is_representative;

CREATE TABLE IF NOT EXISTS support_staff (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id   UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  full_name       TEXT,
  dob             DATE,
  workplace       TEXT,
  title           TEXT,
  qualification   TEXT,
  support_content TEXT
);

CREATE TABLE IF NOT EXISTS evidence_files (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id   UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  kind            TEXT NOT NULL CHECK (kind IN ('textbook','research','technical')),
  storage_uri     TEXT NOT NULL,
  original_name   TEXT NOT NULL,
  mime_type       TEXT NOT NULL DEFAULT 'application/pdf',
  byte_size       BIGINT NOT NULL,
  sha256          CHAR(64) NOT NULL,
  uploaded_by     UUID NOT NULL REFERENCES users(id),
  uploaded_at     TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS uq_evidence_kind ON evidence_files(initiative_id, kind);

-- =========  BÁO CÁO (REPORT)  =========
CREATE TABLE IF NOT EXISTS reports (
  initiative_id        UUID PRIMARY KEY REFERENCES initiatives(id) ON DELETE CASCADE,
  introduction         TEXT,
  representative_phone TEXT,
  representative_email TEXT,
  current_status       TEXT,
  purpose              TEXT,
  implementation_steps TEXT,
  first_applied_unit   TEXT,
  achieved_result      TEXT,
  novelty              TEXT,
  effectiveness        JSONB NOT NULL DEFAULT '{}'::jsonb,
  submission_date      DATE
);

CREATE TABLE IF NOT EXISTS trial_units (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id   UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  name            TEXT NOT NULL,
  address         TEXT,
  field           TEXT,
  ordinal         SMALLINT
);

-- =========  CONTRIBUTION CONFIRMATION  =========
CREATE TABLE IF NOT EXISTS contributions (
  initiative_id               UUID PRIMARY KEY REFERENCES initiatives(id) ON DELETE CASCADE,
  main_author                 TEXT NOT NULL,
  position                    TEXT,
  representative_percent      NUMERIC(5,2),
  submission_date             TIMESTAMPTZ,
  digital_signature_confirmed BOOLEAN NOT NULL DEFAULT FALSE
);

CREATE TABLE IF NOT EXISTS contribution_participants (
  id                   UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id        UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  full_name            TEXT,
  work_unit            TEXT,
  contribution_percent NUMERIC(5,2)
);

-- =========  PHIẾU ĐÁNH GIÁ  =========
CREATE TABLE IF NOT EXISTS evaluations (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id         UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  council_member_id     UUID NOT NULL REFERENCES users(id),
  position              TEXT,
  evaluation_date       DATE NOT NULL,
  novelty_level         eval_level,
  novelty_score         SMALLINT,
  novelty_comment       TEXT,
  effectiveness_level   eval_level,
  effectiveness_score   SMALLINT,
  effectiveness_comment TEXT,
  total_score           SMALLINT GENERATED ALWAYS AS
                        (COALESCE(novelty_score,0) + COALESCE(effectiveness_score,0)) STORED,
  conclusion            TEXT,
  status                submission_status NOT NULL DEFAULT 'draft',
  submitted_at          TIMESTAMPTZ,
  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  CHECK (novelty_score       IS NULL OR (novelty_score BETWEEN 0 AND 40)),
  CHECK (effectiveness_score IS NULL OR (effectiveness_score BETWEEN 0 AND 60)),
  UNIQUE (initiative_id, council_member_id)
);
CREATE INDEX IF NOT EXISTS idx_eval_initiative ON evaluations(initiative_id);

-- =========  ADMIN VERIFY  =========
CREATE TABLE IF NOT EXISTS verifications (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  initiative_id UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
  field_name    TEXT NOT NULL,
  content_hash  CHAR(64) NOT NULL,
  verified_by   UUID NOT NULL REFERENCES users(id),
  verified_at   TIMESTAMPTZ NOT NULL DEFAULT now(),
  result        TEXT
);

-- =========  AUDIT TRAIL  =========
CREATE TABLE IF NOT EXISTS audit_log (
  id          BIGSERIAL PRIMARY KEY,
  actor_id    UUID REFERENCES users(id),
  action      TEXT NOT NULL,
  entity      TEXT NOT NULL,
  entity_id   UUID NOT NULL,
  diff        JSONB,
  occurred_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_audit_entity ON audit_log(entity, entity_id);
