create table if not exists public.exam_dates (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  region_id uuid references public.regions(id) on delete set null,
  school_id uuid references public.schools(id) on delete set null,
  legacy_id text,
  exam_name text not null,
  exam_date date,
  exam_type text,
  sort_order integer not null default 0,
  is_active boolean not null default true,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id)
);

create table if not exists public.question_type_groups (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  subject_id uuid references public.subjects(id) on delete cascade,
  legacy_id text,
  legacy_subject_id text,
  display_name text not null,
  types jsonb not null default '[]'::jsonb,
  sort_order integer not null default 0,
  is_active boolean not null default true,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id)
);

create table if not exists public.subject_shares (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  source_subject_id uuid references public.subjects(id) on delete cascade,
  target_subject_id uuid references public.subjects(id) on delete cascade,
  legacy_id text,
  legacy_source_subject_id text,
  legacy_target_subject_id text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id)
);

create table if not exists public.recent_practices (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  user_id uuid references public.platform_users(id) on delete cascade,
  legacy_id text,
  practice_type text,
  target_legacy_id text,
  target_name text,
  progress integer not null default 0,
  color text,
  last_access_at timestamptz,
  last_practice_at timestamptz,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id)
);

create table if not exists public.user_word_progress (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  user_id uuid references public.platform_users(id) on delete cascade,
  word_id uuid references public.vocabulary_words(id) on delete cascade,
  legacy_id text,
  legacy_user_id text,
  legacy_word_id text,
  status text not null default 'new' check (status in ('new', 'learning', 'mastered', 'reviewing')),
  correct_count integer not null default 0,
  wrong_count integer not null default 0,
  last_review_date timestamptz,
  next_review_date timestamptz,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id),
  unique (tenant_id, user_id, word_id)
);

create table if not exists public.user_word_favorites (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  user_id uuid references public.platform_users(id) on delete cascade,
  word_id uuid references public.vocabulary_words(id) on delete cascade,
  legacy_id text,
  legacy_user_id text,
  legacy_word_id text,
  note text,
  favorited_at timestamptz,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id),
  unique (tenant_id, user_id, word_id)
);

create table if not exists public.content_assets (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  legacy_id text,
  asset_key text,
  title text,
  category text,
  description text,
  file_name text,
  cdn_url text,
  is_public boolean not null default false,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, legacy_id)
);

create table if not exists public.dashboard_daily_stats (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  legacy_id text,
  stat_date date not null,
  region_id uuid references public.regions(id) on delete set null,
  legacy_region_id text,
  new_users integer not null default 0,
  new_questions integer not null default 0,
  new_orders integer not null default 0,
  new_revenue_cents integer not null default 0,
  active_users integer not null default 0,
  rebuilt_at timestamptz,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, stat_date, legacy_region_id)
);

create table if not exists public.revenue_daily_stats (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  legacy_id text,
  stat_date date not null,
  region_id uuid references public.regions(id) on delete set null,
  legacy_region_id text,
  sale_type text,
  real_revenue_cents integer not null default 0,
  order_count integer not null default 0,
  code_count integer not null default 0,
  code_used integer not null default 0,
  code_estimated_cents integer not null default 0,
  estimated_revenue_cents integer not null default 0,
  rebuilt_at timestamptz,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, stat_date, legacy_region_id, sale_type)
);

create index if not exists idx_exam_dates_tenant_region on public.exam_dates(tenant_id, region_id, exam_date);
create index if not exists idx_question_type_groups_subject on public.question_type_groups(tenant_id, subject_id, sort_order);
create index if not exists idx_recent_practices_user on public.recent_practices(tenant_id, user_id, last_practice_at desc);
create index if not exists idx_user_word_progress_user on public.user_word_progress(tenant_id, user_id, status);
create index if not exists idx_content_assets_tenant_key on public.content_assets(tenant_id, asset_key);
create index if not exists idx_dashboard_daily_stats_date on public.dashboard_daily_stats(tenant_id, stat_date desc);
create index if not exists idx_revenue_daily_stats_date on public.revenue_daily_stats(tenant_id, stat_date desc);

do $$
declare
  table_name text;
begin
  foreach table_name in array array[
    'exam_dates', 'question_type_groups', 'subject_shares', 'recent_practices',
    'user_word_progress', 'user_word_favorites', 'content_assets',
    'dashboard_daily_stats', 'revenue_daily_stats'
  ]
  loop
    execute format('alter table public.%I enable row level security', table_name);
    execute format('drop policy if exists tenant_isolation on public.%I', table_name);
    execute format(
      'create policy tenant_isolation on public.%I for all using (tenant_id = app.current_tenant_id() or app.is_platform_admin()) with check (tenant_id = app.current_tenant_id() or app.is_platform_admin())',
      table_name
    );
    execute format('drop trigger if exists set_updated_at on public.%I', table_name);
    execute format('create trigger set_updated_at before update on public.%I for each row execute function app.touch_updated_at()', table_name);
  end loop;
end $$;
