-- Migration: Billing tables for subscription management
-- Supports: Free/Pro/Team plans, Alipay + WeChat Pay, usage quotas

-- Plan definitions (Free/Pro/Team)
CREATE TABLE IF NOT EXISTS billing_plans (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL UNIQUE,
    display_name TEXT NOT NULL,
    description TEXT,
    price_cents INTEGER NOT NULL DEFAULT 0,
    currency TEXT NOT NULL DEFAULT 'CNY',
    interval TEXT NOT NULL DEFAULT 'month',
    features JSONB NOT NULL DEFAULT '{}',
    limits JSONB NOT NULL DEFAULT '{}',
    is_default BOOLEAN NOT NULL DEFAULT FALSE,
    sort_order INTEGER NOT NULL DEFAULT 0,
    status TEXT NOT NULL DEFAULT 'active',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_billing_plans_status ON billing_plans(status);

-- Account subscriptions
CREATE TABLE IF NOT EXISTS billing_subscriptions (
    id TEXT PRIMARY KEY,
    account_id TEXT NOT NULL,
    plan_id TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'active',
    current_period_start TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    current_period_end TIMESTAMPTZ NOT NULL,
    trial_end TIMESTAMPTZ,
    canceled_at TIMESTAMPTZ,
    cancel_at_period_end BOOLEAN NOT NULL DEFAULT FALSE,
    metadata JSONB NOT NULL DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE,
    FOREIGN KEY (plan_id) REFERENCES billing_plans(id)
);
CREATE INDEX IF NOT EXISTS idx_billing_sub_account ON billing_subscriptions(account_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_billing_sub_active
    ON billing_subscriptions(account_id)
    WHERE status IN ('trial', 'active', 'past_due');

-- Invoices
CREATE TABLE IF NOT EXISTS billing_invoices (
    id TEXT PRIMARY KEY,
    account_id TEXT NOT NULL,
    subscription_id TEXT,
    plan_id TEXT,
    amount_cents INTEGER NOT NULL,
    currency TEXT NOT NULL DEFAULT 'CNY',
    description TEXT,
    status TEXT NOT NULL DEFAULT 'pending',
    due_at TIMESTAMPTZ,
    paid_at TIMESTAMPTZ,
    voided_at TIMESTAMPTZ,
    metadata JSONB NOT NULL DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE,
    FOREIGN KEY (subscription_id) REFERENCES billing_subscriptions(id) ON DELETE SET NULL,
    FOREIGN KEY (plan_id) REFERENCES billing_plans(id)
);
CREATE INDEX IF NOT EXISTS idx_billing_inv_account ON billing_invoices(account_id);
CREATE INDEX IF NOT EXISTS idx_billing_inv_status ON billing_invoices(status);
CREATE INDEX IF NOT EXISTS idx_billing_inv_time ON billing_invoices(created_at);

-- Payment records (Alipay / WeChat Pay)
CREATE TABLE IF NOT EXISTS billing_payments (
    id TEXT PRIMARY KEY,
    invoice_id TEXT NOT NULL,
    account_id TEXT NOT NULL,
    amount_cents INTEGER NOT NULL,
    currency TEXT NOT NULL DEFAULT 'CNY',
    method TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    external_trade_no TEXT,
    paid_at TIMESTAMPTZ,
    refunded_at TIMESTAMPTZ,
    failure_reason TEXT,
    metadata JSONB NOT NULL DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    FOREIGN KEY (invoice_id) REFERENCES billing_invoices(id) ON DELETE CASCADE,
    FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_billing_pay_invoice ON billing_payments(invoice_id);
CREATE INDEX IF NOT EXISTS idx_billing_pay_account ON billing_payments(account_id);
CREATE INDEX IF NOT EXISTS idx_billing_pay_trade_no ON billing_payments(external_trade_no);
CREATE INDEX IF NOT EXISTS idx_billing_pay_status ON billing_payments(status);

-- Monthly usage quotas (per account per billing period)
CREATE TABLE IF NOT EXISTS billing_usage_quotas (
    id TEXT PRIMARY KEY,
    account_id TEXT NOT NULL,
    period_start TIMESTAMPTZ NOT NULL,
    period_end TIMESTAMPTZ NOT NULL,
    input_tokens BIGINT NOT NULL DEFAULT 0,
    output_tokens BIGINT NOT NULL DEFAULT 0,
    relay_requests INTEGER NOT NULL DEFAULT 0,
    hand_executions INTEGER NOT NULL DEFAULT 0,
    pipeline_runs INTEGER NOT NULL DEFAULT 0,
    max_input_tokens BIGINT,
    max_output_tokens BIGINT,
    max_relay_requests INTEGER,
    max_hand_executions INTEGER,
    max_pipeline_runs INTEGER,
    metadata JSONB NOT NULL DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE CASCADE,
    UNIQUE(account_id, period_start)
);
CREATE INDEX IF NOT EXISTS idx_billing_usage_account ON billing_usage_quotas(account_id);
CREATE INDEX IF NOT EXISTS idx_billing_usage_period ON billing_usage_quotas(period_start, period_end);

-- Seed: default plans
INSERT INTO billing_plans (id, name, display_name, description, price_cents, interval, features, limits, is_default, sort_order)
VALUES
    ('plan-free', 'free', '免费版', '基础功能，适合个人体验', 0, 'month',
     '{"hands": ["browser", "collector", "researcher"], "chat_modes": ["flash", "thinking"], "pipelines": 3, "support": "community"}'::jsonb,
     '{"max_input_tokens_monthly": 500000, "max_output_tokens_monthly": 500000, "max_relay_requests_monthly": 100, "max_hand_executions_monthly": 20, "max_pipeline_runs_monthly": 5}'::jsonb,
     TRUE, 0),
    ('plan-pro', 'pro', '专业版', '全功能解锁，适合知识工作者', 4900, 'month',
     '{"hands": "all", "chat_modes": "all", "pipelines": -1, "support": "priority", "memory": true, "export": true}'::jsonb,
     '{"max_input_tokens_monthly": 5000000, "max_output_tokens_monthly": 5000000, "max_relay_requests_monthly": 2000, "max_hand_executions_monthly": 200, "max_pipeline_runs_monthly": 100}'::jsonb,
     FALSE, 1),
    ('plan-team', 'team', '团队版', '多席位协作，适合企业团队', 19900, 'month',
     '{"hands": "all", "chat_modes": "all", "pipelines": -1, "support": "dedicated", "memory": true, "export": true, "sharing": true, "admin": true}'::jsonb,
     '{"max_input_tokens_monthly": 50000000, "max_output_tokens_monthly": 50000000, "max_relay_requests_monthly": 20000, "max_hand_executions_monthly": 1000, "max_pipeline_runs_monthly": 500}'::jsonb,
     FALSE, 2)
ON CONFLICT (name) DO NOTHING;
