-- PostgreSQL schema (MVP)
-- Note: This schema is optimized for low volume and long-term retention.
-- Future expansion: add delivery_detail / tracking_detail tables if needed.

-- Extensions
CREATE EXTENSION IF NOT EXISTS citext;

-- Tenants (optional; can be sourced from Member Center if not stored locally)
CREATE TABLE IF NOT EXISTS tenants (
  id UUID PRIMARY KEY,
  name TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Lists (per tenant)
CREATE TABLE IF NOT EXISTS lists (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  name TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_lists_tenant ON lists(tenant_id);

ALTER TABLE lists
  ADD CONSTRAINT fk_lists_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

-- Subscribers (per tenant)
CREATE TABLE IF NOT EXISTS subscribers (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  email CITEXT NOT NULL,
  status TEXT NOT NULL, -- active/unsubscribed/bounced/complaint
  preferences JSONB,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, email)
);
CREATE INDEX IF NOT EXISTS idx_subscribers_tenant ON subscribers(tenant_id);

ALTER TABLE subscribers
  ADD CONSTRAINT fk_subscribers_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

-- List membership snapshot
CREATE TABLE IF NOT EXISTS list_members (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  list_id UUID NOT NULL,
  subscriber_id UUID NOT NULL,
  status TEXT NOT NULL, -- active/unsubscribed/bounced/complaint
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, list_id, subscriber_id)
);
CREATE INDEX IF NOT EXISTS idx_list_members_tenant ON list_members(tenant_id);
CREATE INDEX IF NOT EXISTS idx_list_members_list ON list_members(list_id);

ALTER TABLE list_members
  ADD CONSTRAINT fk_list_members_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

ALTER TABLE list_members
  ADD CONSTRAINT fk_list_members_list
  FOREIGN KEY (list_id) REFERENCES lists(id);

ALTER TABLE list_members
  ADD CONSTRAINT fk_list_members_subscriber
  FOREIGN KEY (subscriber_id) REFERENCES subscribers(id);

-- Event inbox (append-only)
CREATE TABLE IF NOT EXISTS events_inbox (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  event_type TEXT NOT NULL,
  source TEXT NOT NULL, -- member_center / ses
  payload JSONB NOT NULL,
  received_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  processed_at TIMESTAMPTZ,
  status TEXT NOT NULL DEFAULT 'received', -- received/processed/invalid/failed
  error TEXT
);
CREATE INDEX IF NOT EXISTS idx_events_inbox_tenant ON events_inbox(tenant_id);
CREATE INDEX IF NOT EXISTS idx_events_inbox_type ON events_inbox(event_type);
CREATE INDEX IF NOT EXISTS idx_events_inbox_status ON events_inbox(status);

ALTER TABLE events_inbox
  ADD CONSTRAINT fk_events_inbox_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

-- Campaigns (content is provided by tenant sites)
CREATE TABLE IF NOT EXISTS campaigns (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  list_id UUID NOT NULL,
  name TEXT,
  subject TEXT,
  body_html TEXT,
  body_text TEXT,
  template JSONB, -- optional template payload
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_campaigns_tenant ON campaigns(tenant_id);

ALTER TABLE campaigns
  ADD CONSTRAINT fk_campaigns_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

ALTER TABLE campaigns
  ADD CONSTRAINT fk_campaigns_list
  FOREIGN KEY (list_id) REFERENCES lists(id);

-- Send jobs
CREATE TABLE IF NOT EXISTS send_jobs (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  list_id UUID NOT NULL,
  campaign_id UUID NOT NULL,
  scheduled_at TIMESTAMPTZ,
  window_start TIMESTAMPTZ,
  window_end TIMESTAMPTZ,
  status TEXT NOT NULL DEFAULT 'pending', -- pending/running/completed/failed/cancelled
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_send_jobs_tenant ON send_jobs(tenant_id);
CREATE INDEX IF NOT EXISTS idx_send_jobs_status ON send_jobs(status);

ALTER TABLE send_jobs
  ADD CONSTRAINT fk_send_jobs_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

ALTER TABLE send_jobs
  ADD CONSTRAINT fk_send_jobs_list
  FOREIGN KEY (list_id) REFERENCES lists(id);

ALTER TABLE send_jobs
  ADD CONSTRAINT fk_send_jobs_campaign
  FOREIGN KEY (campaign_id) REFERENCES campaigns(id);

-- Outbox (batches to send)
CREATE TABLE IF NOT EXISTS send_batches (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  send_job_id UUID NOT NULL,
  status TEXT NOT NULL DEFAULT 'queued', -- queued/sending/done/failed
  size INT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_send_batches_job ON send_batches(send_job_id);
CREATE INDEX IF NOT EXISTS idx_send_batches_status ON send_batches(status);

ALTER TABLE send_batches
  ADD CONSTRAINT fk_send_batches_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

ALTER TABLE send_batches
  ADD CONSTRAINT fk_send_batches_job
  FOREIGN KEY (send_job_id) REFERENCES send_jobs(id);

-- Delivery summary (no per-recipient details for MVP)
CREATE TABLE IF NOT EXISTS delivery_summary (
  id UUID PRIMARY KEY,
  tenant_id UUID NOT NULL,
  send_job_id UUID NOT NULL,
  total INT NOT NULL DEFAULT 0,
  delivered INT NOT NULL DEFAULT 0,
  bounced INT NOT NULL DEFAULT 0,
  complained INT NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, send_job_id)
);
CREATE INDEX IF NOT EXISTS idx_delivery_summary_job ON delivery_summary(send_job_id);

ALTER TABLE delivery_summary
  ADD CONSTRAINT fk_delivery_summary_tenant
  FOREIGN KEY (tenant_id) REFERENCES tenants(id);

ALTER TABLE delivery_summary
  ADD CONSTRAINT fk_delivery_summary_job
  FOREIGN KEY (send_job_id) REFERENCES send_jobs(id);

-- Auth: trusted clients for this service (prevent abuse)
-- Member Center and tenant sites are registered here.
CREATE TABLE IF NOT EXISTS auth_clients (
  id UUID PRIMARY KEY,
  tenant_id UUID, -- NULL for Member Center or global services
  client_id TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  scopes TEXT[] NOT NULL,
  status TEXT NOT NULL DEFAULT 'active', -- active/disabled
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_auth_clients_tenant ON auth_clients(tenant_id);

-- API keys for HMAC or simple client auth (store hash only)
CREATE TABLE IF NOT EXISTS auth_client_keys (
  id UUID PRIMARY KEY,
  client_id UUID NOT NULL,
  key_hash TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  revoked_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_auth_client_keys_client ON auth_client_keys(client_id);

ALTER TABLE auth_client_keys
  ADD CONSTRAINT fk_auth_client_keys_client
  FOREIGN KEY (client_id) REFERENCES auth_clients(id);

-- Replay protection for signed webhooks (optional)
CREATE TABLE IF NOT EXISTS webhook_nonces (
  id UUID PRIMARY KEY,
  client_id UUID NOT NULL,
  nonce TEXT NOT NULL,
  received_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (client_id, nonce)
);
CREATE INDEX IF NOT EXISTS idx_webhook_nonces_client ON webhook_nonces(client_id);

ALTER TABLE webhook_nonces
  ADD CONSTRAINT fk_webhook_nonces_client
  FOREIGN KEY (client_id) REFERENCES auth_clients(id);
