alter table public.video_explanations
  add column if not exists asset_id uuid references public.content_assets(id) on delete set null,
  add column if not exists access_mode text not null default 'svip',
  add column if not exists free_preview_seconds integer not null default 0,
  add column if not exists play_count integer not null default 0;

do $$
begin
  if not exists (select 1 from pg_constraint where conname = 'video_explanations_access_mode_check') then
    alter table public.video_explanations
      add constraint video_explanations_access_mode_check
      check (access_mode in ('free', 'svip', 'video_quota'));
  end if;

  if not exists (select 1 from pg_constraint where conname = 'video_explanations_free_preview_check') then
    alter table public.video_explanations
      add constraint video_explanations_free_preview_check
      check (free_preview_seconds >= 0);
  end if;

  if not exists (select 1 from pg_constraint where conname = 'video_explanations_play_count_check') then
    alter table public.video_explanations
      add constraint video_explanations_play_count_check
      check (play_count >= 0);
  end if;
end $$;

create table if not exists public.video_play_quota_accounts (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  user_id uuid not null references public.platform_users(id) on delete cascade,
  quota_type text not null default 'video_play',
  total_quota integer not null default 0,
  used_quota integer not null default 0,
  expires_at timestamptz,
  source_type text,
  source_id uuid,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (tenant_id, user_id, quota_type, source_type, source_id)
);

create table if not exists public.video_play_events (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  user_id uuid not null references public.platform_users(id) on delete cascade,
  video_id uuid not null references public.video_explanations(id) on delete cascade,
  question_id uuid references public.questions(id) on delete set null,
  entitlement_id uuid references public.entitlements(id) on delete set null,
  quota_account_id uuid references public.video_play_quota_accounts(id) on delete set null,
  play_token_hash text not null unique,
  status text not null default 'issued' check (status in ('issued', 'started', 'completed', 'expired', 'revoked')),
  access_mode text not null default 'svip' check (access_mode in ('free', 'svip', 'video_quota')),
  consumed_quota integer not null default 0 check (consumed_quota >= 0),
  signed_url_expires_at timestamptz,
  ip_address text,
  user_agent text,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create index if not exists idx_video_explanations_asset
  on public.video_explanations(tenant_id, asset_id)
  where asset_id is not null;

create index if not exists idx_video_quota_user
  on public.video_play_quota_accounts(tenant_id, user_id, quota_type, expires_at);

create index if not exists idx_video_play_events_user
  on public.video_play_events(tenant_id, user_id, created_at desc);

create index if not exists idx_video_play_events_video
  on public.video_play_events(tenant_id, video_id, created_at desc);

do $$
declare
  table_name text;
begin
  foreach table_name in array array['video_play_quota_accounts', 'video_play_events']
  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 $$;
