create table if not exists public.platform_saas_plans (
  id uuid primary key default gen_random_uuid(),
  code text not null unique,
  name text not null,
  description text,
  billing_cycle text not null default 'yearly' check (billing_cycle in ('monthly', 'quarterly', 'yearly', 'one_time')),
  base_amount_cents integer not null default 0,
  currency text not null default 'CNY',
  included_quotas jsonb not null default '{}'::jsonb,
  overage_prices jsonb not null default '{}'::jsonb,
  feature_flags jsonb not null default '{}'::jsonb,
  status text not null default 'active' check (status in ('active', 'archived')),
  sort_order integer not null default 0,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table if not exists public.tenant_billing_profiles (
  tenant_id uuid primary key references public.tenants(id) on delete cascade,
  billing_name text,
  tax_id text,
  contact_name text,
  contact_phone text,
  contact_email citext,
  billing_address text,
  invoice_title text,
  invoice_type text check (invoice_type in ('none', 'normal_vat', 'special_vat')),
  bank_name text,
  bank_account_masked text,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table if not exists public.tenant_invoices (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  invoice_no text not null unique,
  invoice_type text not null default 'subscription' check (invoice_type in ('subscription', 'service_fee', 'usage_overage', 'manual_adjustment')),
  status text not null default 'draft' check (status in ('draft', 'issued', 'paid', 'void', 'overdue')),
  currency text not null default 'CNY',
  subtotal_cents integer not null default 0,
  discount_cents integer not null default 0,
  tax_cents integer not null default 0,
  total_cents integer not null default 0,
  paid_cents integer not null default 0,
  balance_cents integer not null default 0,
  billing_period_start date,
  billing_period_end date,
  due_date date,
  issued_at timestamptz,
  paid_at timestamptz,
  note text,
  metadata jsonb not null default '{}'::jsonb,
  created_by uuid references public.platform_users(id) on delete set null,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table if not exists public.tenant_invoice_items (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  invoice_id uuid not null references public.tenant_invoices(id) on delete cascade,
  item_type text not null default 'subscription',
  item_ref_id uuid,
  description text not null,
  quantity numeric(12,2) not null default 1,
  unit_amount_cents integer not null default 0,
  amount_cents integer not null default 0,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now()
);

create table if not exists public.tenant_invoice_payments (
  id uuid primary key default gen_random_uuid(),
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  invoice_id uuid not null references public.tenant_invoices(id) on delete cascade,
  payment_no text not null unique,
  provider text not null default 'manual',
  method text,
  status text not null default 'paid' check (status in ('pending', 'paid', 'failed', 'refunded')),
  amount_cents integer not null default 0,
  paid_at timestamptz,
  provider_trade_no text,
  received_by uuid references public.platform_users(id) on delete set null,
  raw_payload 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_saas_plans_status on public.platform_saas_plans(status, sort_order);
create index if not exists idx_tenant_subscriptions_tenant_status on public.tenant_subscriptions(tenant_id, status, expires_at desc);
create index if not exists idx_tenant_usage_records_lookup on public.tenant_usage_records(tenant_id, metric_key, period_start, period_end);
create index if not exists idx_tenant_invoices_tenant_status on public.tenant_invoices(tenant_id, status, due_date desc);
create index if not exists idx_tenant_invoice_items_invoice on public.tenant_invoice_items(invoice_id);
create index if not exists idx_tenant_invoice_payments_invoice on public.tenant_invoice_payments(invoice_id, status);

alter table public.platform_saas_plans enable row level security;
alter table public.tenant_billing_profiles enable row level security;
alter table public.tenant_invoices enable row level security;
alter table public.tenant_invoice_items enable row level security;
alter table public.tenant_invoice_payments enable row level security;

drop policy if exists platform_admin_saas_plans on public.platform_saas_plans;
create policy platform_admin_saas_plans on public.platform_saas_plans
  for all
  using (app.is_platform_admin())
  with check (app.is_platform_admin());

do $$
declare
  table_name text;
begin
  foreach table_name in array array[
    'tenant_billing_profiles',
    'tenant_invoices',
    'tenant_invoice_items',
    'tenant_invoice_payments'
  ]
  loop
    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
    );
  end loop;
end $$;

do $$
declare
  table_name text;
begin
  foreach table_name in array array[
    'platform_saas_plans',
    'tenant_billing_profiles',
    'tenant_invoices',
    'tenant_invoice_payments'
  ]
  loop
    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 $$;

insert into public.platform_saas_plans (
  code, name, description, billing_cycle, base_amount_cents,
  included_quotas, overage_prices, feature_flags, sort_order
)
values
  (
    'starter_yearly',
    '合作商基础版',
    '适合单地区题库合作商，含基础品牌与域名能力。',
    'yearly',
    980000,
    '{"students":1000,"questions":5000,"storageGb":20}'::jsonb,
    '{"studentsExtraPerYearCents":500,"storageGbPerYearCents":12000}'::jsonb,
    '{"customDomain":true,"tenantBranding":true,"paymentTenantCollect":false}'::jsonb,
    10
  ),
  (
    'pro_yearly',
    '合作商专业版',
    '适合多地区、多课程运营，支持更多运营工具。',
    'yearly',
    1980000,
    '{"students":5000,"questions":30000,"storageGb":100}'::jsonb,
    '{"studentsExtraPerYearCents":300,"storageGbPerYearCents":9000}'::jsonb,
    '{"customDomain":true,"tenantBranding":true,"paymentTenantCollect":true,"crmWebhook":true}'::jsonb,
    20
  )
on conflict (code)
do update set name = excluded.name,
              description = excluded.description,
              billing_cycle = excluded.billing_cycle,
              base_amount_cents = excluded.base_amount_cents,
              included_quotas = excluded.included_quotas,
              overage_prices = excluded.overage_prices,
              feature_flags = excluded.feature_flags,
              sort_order = excluded.sort_order,
              updated_at = now();
