-- ============================================
-- TEMPLATE-SAAS: Invoices & Payments
-- Schema: billing
-- Version: 1.0.0
-- ============================================

CREATE TABLE billing.invoices (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    subscription_id UUID REFERENCES billing.subscriptions(id),

    -- Invoice number
    invoice_number VARCHAR(50) UNIQUE NOT NULL,

    -- Stripe
    stripe_invoice_id VARCHAR(255) UNIQUE,

    -- Status
    status billing.invoice_status DEFAULT 'draft' NOT NULL,

    -- Amounts
    subtotal DECIMAL(10, 2) NOT NULL DEFAULT 0,
    tax DECIMAL(10, 2) DEFAULT 0,
    discount DECIMAL(10, 2) DEFAULT 0,
    total DECIMAL(10, 2) NOT NULL DEFAULT 0,
    amount_paid DECIMAL(10, 2) DEFAULT 0,
    amount_due DECIMAL(10, 2) NOT NULL DEFAULT 0,
    currency VARCHAR(3) DEFAULT 'USD',

    -- Dates
    invoice_date DATE NOT NULL DEFAULT CURRENT_DATE,
    due_date DATE,
    paid_at TIMESTAMPTZ,

    -- Period
    period_start DATE,
    period_end DATE,

    -- PDF
    invoice_pdf_url VARCHAR(500),
    hosted_invoice_url VARCHAR(500),

    -- Customer info at time of invoice
    customer_name VARCHAR(255),
    customer_email VARCHAR(255),
    billing_address JSONB,

    -- Metadata
    metadata JSONB DEFAULT '{}'::jsonb,
    notes TEXT,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);

-- Invoice line items
CREATE TABLE billing.invoice_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    invoice_id UUID NOT NULL REFERENCES billing.invoices(id) ON DELETE CASCADE,

    -- Description
    description VARCHAR(500) NOT NULL,
    quantity INT DEFAULT 1,

    -- Pricing
    unit_amount DECIMAL(10, 2) NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    currency VARCHAR(3) DEFAULT 'USD',

    -- Period (for subscription items)
    period_start DATE,
    period_end DATE,

    -- Stripe
    stripe_invoice_item_id VARCHAR(255),

    -- Metadata
    metadata JSONB DEFAULT '{}'::jsonb,

    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);

-- Payments
CREATE TABLE billing.payments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    invoice_id UUID REFERENCES billing.invoices(id),

    -- Stripe
    stripe_payment_intent_id VARCHAR(255) UNIQUE,
    stripe_charge_id VARCHAR(255),

    -- Amount
    amount DECIMAL(10, 2) NOT NULL,
    currency VARCHAR(3) DEFAULT 'USD',

    -- Status
    status billing.payment_status DEFAULT 'pending' NOT NULL,

    -- Payment method
    payment_method_type VARCHAR(50),  -- 'card', 'bank_transfer', etc.
    payment_method_last4 VARCHAR(4),
    payment_method_brand VARCHAR(50),

    -- Failure info
    failure_code VARCHAR(100),
    failure_message TEXT,

    -- Dates
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    succeeded_at TIMESTAMPTZ,
    failed_at TIMESTAMPTZ,
    refunded_at TIMESTAMPTZ,

    -- Refund info
    refund_amount DECIMAL(10, 2),
    refund_reason VARCHAR(500)
);

-- Indexes
CREATE INDEX idx_invoices_tenant ON billing.invoices(tenant_id);
CREATE INDEX idx_invoices_subscription ON billing.invoices(subscription_id);
CREATE INDEX idx_invoices_status ON billing.invoices(status);
CREATE INDEX idx_invoices_stripe ON billing.invoices(stripe_invoice_id);
CREATE INDEX idx_invoice_items_invoice ON billing.invoice_items(invoice_id);
CREATE INDEX idx_payments_tenant ON billing.payments(tenant_id);
CREATE INDEX idx_payments_invoice ON billing.payments(invoice_id);
CREATE INDEX idx_payments_stripe ON billing.payments(stripe_payment_intent_id);

-- RLS
ALTER TABLE billing.invoices ENABLE ROW LEVEL SECURITY;
ALTER TABLE billing.invoice_items ENABLE ROW LEVEL SECURITY;
ALTER TABLE billing.payments ENABLE ROW LEVEL SECURITY;

CREATE POLICY invoices_tenant_isolation ON billing.invoices
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

CREATE POLICY invoice_items_tenant_isolation ON billing.invoice_items
    USING (invoice_id IN (
        SELECT id FROM billing.invoices
        WHERE tenant_id = current_setting('app.current_tenant_id', true)::UUID
    ));

CREATE POLICY payments_tenant_isolation ON billing.payments
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Trigger
CREATE TRIGGER trg_invoices_updated_at
    BEFORE UPDATE ON billing.invoices
    FOR EACH ROW
    EXECUTE FUNCTION billing.update_updated_at();

CREATE TRIGGER trg_payments_updated_at
    BEFORE UPDATE ON billing.payments
    FOR EACH ROW
    EXECUTE FUNCTION billing.update_updated_at();

-- Invoice number sequence
CREATE SEQUENCE billing.invoice_number_seq START 1000;

-- Function to generate invoice number
CREATE OR REPLACE FUNCTION billing.generate_invoice_number()
RETURNS VARCHAR AS $$
BEGIN
    RETURN 'INV-' || TO_CHAR(NOW(), 'YYYYMM') || '-' || LPAD(nextval('billing.invoice_number_seq')::TEXT, 6, '0');
END;
$$ LANGUAGE plpgsql;

-- Comments
COMMENT ON TABLE billing.invoices IS 'Invoices generated for billing';
COMMENT ON TABLE billing.invoice_items IS 'Line items within an invoice';
COMMENT ON TABLE billing.payments IS 'Payment records and attempts';
