-- User staff profiles (1:1 with users) — HR / verification workflow
-- Apply: docker exec -i initiative-postgres psql -U initiative -d initiatives < be0/migrations/010_user_staff_profiles.sql

DO $$ BEGIN
  CREATE TYPE profile_verification_status AS ENUM ('draft', 'pending', 'verified', 'rejected');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

CREATE TABLE IF NOT EXISTS academic_titles (
  code         TEXT PRIMARY KEY,
  label_vi     TEXT NOT NULL,
  label_en     TEXT NOT NULL,
  sort_order   INTEGER NOT NULL DEFAULT 0,
  active       BOOLEAN NOT NULL DEFAULT TRUE
);

INSERT INTO academic_titles (code, label_vi, label_en, sort_order) VALUES
  ('professor', 'Giáo sư', 'Professor', 10),
  ('associate_professor', 'Phó Giáo sư', 'Associate Professor', 20),
  ('doctor_sc', 'Tiến sĩ', 'Doctor of Science', 30),
  ('bsckii', 'BSCKII', 'Specialist level II', 35),
  ('bscki', 'BSCKI', 'Specialist level I', 36),
  ('master', 'Thạc sĩ', 'Master', 40),
  ('doctor_md', 'Bác sĩ', 'Physician', 45),
  ('pharmacist', 'Dược sĩ', 'Pharmacist', 46),
  ('bachelor', 'Cử nhân', 'Bachelor', 50),
  ('other', 'Khác (ghi rõ)', 'Other (specify)', 100)
ON CONFLICT (code) DO NOTHING;

CREATE TABLE IF NOT EXISTS user_staff_profiles (
  user_id                       UUID PRIMARY KEY
                                  REFERENCES users(id) ON DELETE CASCADE,

  employee_id                   TEXT,
  academic_title_code           TEXT REFERENCES academic_titles(code),
  academic_title_other          TEXT,
  unit_name_freetext            TEXT,
  job_title                     TEXT,

  profile_verification_status   profile_verification_status
                                  NOT NULL DEFAULT 'draft',
  verification_submitted_at     TIMESTAMPTZ,
  verified_at                   TIMESTAMPTZ,
  verified_by_user_id           UUID REFERENCES users(id),
  rejection_reason              TEXT,

  version                       INTEGER NOT NULL DEFAULT 1,
  created_at                    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at                    TIMESTAMPTZ NOT NULL DEFAULT now(),

  CONSTRAINT employee_id_shape
    CHECK (employee_id IS NULL OR employee_id ~ '^[A-Z0-9-]{3,32}$'),

  CONSTRAINT academic_title_other_invariant CHECK (
    CASE
      WHEN academic_title_code IS NULL THEN academic_title_other IS NULL
      WHEN academic_title_code = 'other' THEN
        academic_title_other IS NOT NULL AND length(trim(academic_title_other)) > 0
      ELSE academic_title_other IS NULL
    END
  ),

  CONSTRAINT verified_requires_metadata CHECK (
    profile_verification_status <> 'verified'
    OR (verified_at IS NOT NULL AND verified_by_user_id IS NOT NULL)
  ),

  CONSTRAINT rejected_requires_reason CHECK (
    profile_verification_status <> 'rejected'
    OR (rejection_reason IS NOT NULL AND length(trim(rejection_reason)) > 0)
  ),

  CONSTRAINT non_terminal_clears_verification CHECK (
    profile_verification_status NOT IN ('draft', 'pending')
    OR (verified_at IS NULL AND verified_by_user_id IS NULL)
  ),

  CONSTRAINT rejected_clears_verification_metadata CHECK (
    profile_verification_status <> 'rejected'
    OR (verified_at IS NULL AND verified_by_user_id IS NULL)
  ),

  CONSTRAINT verified_clears_rejection CHECK (
    profile_verification_status <> 'verified'
    OR rejection_reason IS NULL
  ),

  CONSTRAINT job_title_length CHECK (
    job_title IS NULL OR length(job_title) <= 120
  )
);

CREATE UNIQUE INDEX IF NOT EXISTS ix_usp_employee_id_unique
  ON user_staff_profiles (employee_id)
  WHERE employee_id IS NOT NULL;

CREATE INDEX IF NOT EXISTS ix_usp_pending_queue
  ON user_staff_profiles (verification_submitted_at)
  WHERE profile_verification_status = 'pending';

CREATE INDEX IF NOT EXISTS ix_usp_verifier_activity
  ON user_staff_profiles (verified_by_user_id, verified_at DESC)
  WHERE verified_by_user_id IS NOT NULL;

-- Backfill one row per existing user (draft, NULL fields)
INSERT INTO user_staff_profiles (user_id, profile_verification_status)
SELECT u.id, 'draft'::profile_verification_status
FROM users u
WHERE NOT EXISTS (
  SELECT 1 FROM user_staff_profiles p WHERE p.user_id = u.id
);

COMMENT ON TABLE user_staff_profiles IS
  'Institutional staff profile and verification state; scalars only — no MinIO.';
