create extension if not exists pgcrypto;

create type source_type as enum ('local_folder', 'git_repo', 'zip_upload', 'site_crawl');
create type run_status as enum ('queued', 'running', 'done', 'failed', 'cancelled');
create type reconcile_status as enum ('matched', 'changed', 'new', 'orphaned', 'conflicted');

create table projects (
  id uuid primary key default gen_random_uuid(),
  name text not null,
  slug text not null unique,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table project_sources (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  type source_type not null,
  config jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table scan_versions (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  source_id uuid not null references project_sources(id) on delete cascade,
  status run_status not null default 'queued',
  project_index_key text,
  started_at timestamptz,
  completed_at timestamptz,
  error_message text,
  created_at timestamptz not null default now()
);

create table pages (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  logical_key text not null,
  created_at timestamptz not null default now(),
  unique(project_id, logical_key)
);

create table page_versions (
  id uuid primary key default gen_random_uuid(),
  page_id uuid not null references pages(id) on delete cascade,
  scan_version_id uuid not null references scan_versions(id) on delete cascade,
  source_path text not null,
  url_path text,
  title text,
  description text,
  fingerprint text,
  reconcile_status reconcile_status not null default 'new',
  raw jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table sections (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  page_id uuid references pages(id) on delete cascade,
  logical_key text not null,
  created_at timestamptz not null default now(),
  unique(project_id, logical_key)
);

create table section_versions (
  id uuid primary key default gen_random_uuid(),
  section_id uuid not null references sections(id) on delete cascade,
  scan_version_id uuid not null references scan_versions(id) on delete cascade,
  selector text,
  heading text,
  normalized_text_hash text,
  selector_fingerprint text,
  reconcile_status reconcile_status not null default 'new',
  raw jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table media_assets (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  logical_key text not null,
  created_at timestamptz not null default now(),
  unique(project_id, logical_key)
);

create table media_versions (
  id uuid primary key default gen_random_uuid(),
  media_id uuid not null references media_assets(id) on delete cascade,
  scan_version_id uuid not null references scan_versions(id) on delete cascade,
  source_path text not null,
  media_type text not null,
  section_id uuid references sections(id) on delete set null,
  reconcile_status reconcile_status not null default 'new',
  raw jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table runs (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  run_type text not null,
  status run_status not null default 'queued',
  input jsonb not null default '{}'::jsonb,
  output jsonb,
  error_message text,
  started_at timestamptz,
  completed_at timestamptz,
  created_at timestamptz not null default now()
);

create table seeds (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  section_id uuid references sections(id) on delete set null,
  phrase text not null,
  source text not null default 'model',
  selected boolean not null default true,
  reason text,
  confidence numeric(5, 4),
  created_at timestamptz not null default now()
);

create table wordstat_jobs (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  seed_id uuid references seeds(id) on delete set null,
  status run_status not null default 'queued',
  raw_result_key text,
  created_at timestamptz not null default now(),
  completed_at timestamptz
);

create table wordstat_results (
  id uuid primary key default gen_random_uuid(),
  job_id uuid not null references wordstat_jobs(id) on delete cascade,
  phrase text not null,
  frequency integer,
  frequency_group text,
  raw jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table keyword_decisions (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  wordstat_result_id uuid references wordstat_results(id) on delete set null,
  phrase text not null,
  status text not null,
  reason text,
  approved boolean not null default false,
  created_at timestamptz not null default now()
);

create table keyword_map_items (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  section_id uuid references sections(id) on delete cascade,
  keyword_decision_id uuid references keyword_decisions(id) on delete cascade,
  role text not null,
  exact_limit integer,
  soft_forms jsonb not null default '[]'::jsonb,
  approved boolean not null default false,
  created_at timestamptz not null default now()
);

create table optimization_plans (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  payload jsonb not null default '{}'::jsonb,
  approved boolean not null default false,
  created_at timestamptz not null default now()
);

create table drafts (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  page_id uuid references pages(id) on delete cascade,
  status text not null default 'active',
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table draft_items (
  id uuid primary key default gen_random_uuid(),
  draft_id uuid not null references drafts(id) on delete cascade,
  section_id uuid references sections(id) on delete cascade,
  field text not null,
  original_snapshot_key text,
  working_snapshot_key text,
  working_text text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table validations (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  draft_id uuid references drafts(id) on delete set null,
  status text not null,
  summary jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table validation_issues (
  id uuid primary key default gen_random_uuid(),
  validation_id uuid not null references validations(id) on delete cascade,
  severity text not null,
  code text not null,
  message text not null,
  source_ref jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table changesets (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  draft_id uuid references drafts(id) on delete set null,
  validation_id uuid references validations(id) on delete set null,
  status text not null default 'pending',
  backup_key text,
  summary jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  applied_at timestamptz
);

create table changeset_items (
  id uuid primary key default gen_random_uuid(),
  changeset_id uuid not null references changesets(id) on delete cascade,
  change_type text not null,
  source_path text not null,
  selector_or_media_id text,
  before_value text,
  after_value text,
  created_at timestamptz not null default now()
);

create table exports (
  id uuid primary key default gen_random_uuid(),
  project_id uuid not null references projects(id) on delete cascade,
  export_type text not null,
  object_key text not null,
  created_at timestamptz not null default now()
);
