create table if not exists public.platform_dunning_notification_channels (
  id uuid primary key default gen_random_uuid(),
  channel_code text not null unique,
  name text not null,
  description text,
  enabled boolean not null default true,
  provider text not null default 'generic'
    check (provider in ('generic', 'dingtalk', 'feishu', 'wecom')),
  webhook_url text not null,
  secret_ref text,
  reminder_types text[] not null default array['overdue', 'final_notice']::text[],
  reminder_channels text[] not null default array['internal']::text[],
  min_reminder_level integer not null default 1 check (min_reminder_level between 1 and 20),
  tenant_ids uuid[] not null default '{}'::uuid[],
  timeout_sec integer not null default 10 check (timeout_sec between 1 and 60),
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  constraint platform_dunning_notification_reminder_types_check
    check (reminder_types <@ array['due_soon', 'overdue', 'final_notice', 'manual']::text[]),
  constraint platform_dunning_notification_reminder_channels_check
    check (reminder_channels <@ array['manual', 'internal', 'sms', 'email', 'wechat', 'crm']::text[])
);

create table if not exists public.platform_dunning_notification_events (
  id uuid primary key default gen_random_uuid(),
  channel_id uuid not null references public.platform_dunning_notification_channels(id) on delete cascade,
  reminder_id uuid not null references public.tenant_invoice_reminders(id) on delete cascade,
  invoice_id uuid not null references public.tenant_invoices(id) on delete cascade,
  tenant_id uuid not null references public.tenants(id) on delete cascade,
  provider text not null default 'generic'
    check (provider in ('generic', 'dingtalk', 'feishu', 'wecom')),
  status text not null default 'pending'
    check (status in ('pending', 'processing', 'sent', 'retrying', 'failed', 'discarded')),
  attempts integer not null default 0 check (attempts >= 0),
  scheduled_at timestamptz not null default now(),
  next_attempt_at timestamptz,
  last_attempt_at timestamptz,
  sent_at timestamptz,
  last_error text,
  last_http_code integer,
  last_response_summary text,
  request_payload jsonb not null default '{}'::jsonb,
  metadata jsonb not null default '{}'::jsonb,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (channel_id, reminder_id)
);

create index if not exists idx_platform_dunning_notification_channels_enabled
  on public.platform_dunning_notification_channels(enabled, min_reminder_level, channel_code);

create index if not exists idx_platform_dunning_notification_events_due
  on public.platform_dunning_notification_events(status, coalesce(next_attempt_at, scheduled_at), created_at);

create index if not exists idx_platform_dunning_notification_events_reminder
  on public.platform_dunning_notification_events(reminder_id, status, created_at desc);

create index if not exists idx_platform_dunning_notification_events_invoice
  on public.platform_dunning_notification_events(invoice_id, status, created_at desc);

create index if not exists idx_platform_dunning_notification_events_tenant
  on public.platform_dunning_notification_events(tenant_id, status, created_at desc);

alter table public.platform_dunning_notification_channels enable row level security;
alter table public.platform_dunning_notification_events enable row level security;

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

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

drop trigger if exists set_updated_at on public.platform_dunning_notification_channels;
create trigger set_updated_at
  before update on public.platform_dunning_notification_channels
  for each row execute function app.touch_updated_at();

drop trigger if exists set_updated_at on public.platform_dunning_notification_events;
create trigger set_updated_at
  before update on public.platform_dunning_notification_events
  for each row execute function app.touch_updated_at();
