-- ──────────────────────────────────────────────────────────────────────────
-- Invoice hardening and feature additions
-- ──────────────────────────────────────────────────────────────────────────
-- Adds:
--   * GST breakdown (CGST/SGST for intra-state, IGST for inter-state)
--   * Seller and customer billing details
--   * Currency, place-of-supply, invoice-type, notes
--   * paid_at / voided_at / void_reason for the full lifecycle
--   * A new `invoice_line_items` table so each invoice can hold multiple
--     lines (one per package, adjustment, discount, etc.) — required for
--     GST-compliant Indian e-invoicing.
--   * A `billing_profiles` table to store reusable customer billing
--     details (so an invoice doesn't have to capture them on every sale).
--   * A `pdf_object_key` column for the generated PDF stored in B2.
--   * CHECK constraints to keep numerics sane.
-- ──────────────────────────────────────────────────────────────────────────

-- 1. Invoice lifecycle enum
ALTER TABLE invoices
    DROP CONSTRAINT IF EXISTS invoices_status_valid;
ALTER TABLE invoices
    ADD CONSTRAINT invoices_status_valid
    CHECK (status IN ('DRAFT', 'ISSUED', 'PAID', 'VOID', 'REFUNDED'));

-- 2. Currency
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS currency CHAR(3) NOT NULL DEFAULT 'INR';

-- 3. Invoice type
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS invoice_type VARCHAR(20) NOT NULL DEFAULT 'TAX_INVOICE';
ALTER TABLE invoices
    DROP CONSTRAINT IF EXISTS invoices_invoice_type_valid;
ALTER TABLE invoices
    ADD CONSTRAINT invoices_invoice_type_valid
    CHECK (invoice_type IN ('TAX_INVOICE', 'BILL_OF_SUPPLY', 'CREDIT_NOTE', 'DEBIT_NOTE'));

-- 4. GST breakdown (percentages as basis points * 100 to keep numerics)
-- Stored as numeric so admin tools can display "9% / 9%" or "18% / 18%".
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS cgst_rate NUMERIC(5,2) NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS cgst_amount INTEGER NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS sgst_rate NUMERIC(5,2) NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS sgst_amount INTEGER NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS igst_rate NUMERIC(5,2) NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS igst_amount INTEGER NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS place_of_supply_state VARCHAR(2),
    ADD COLUMN IF NOT EXISTS seller_state VARCHAR(2),
    ADD COLUMN IF NOT EXISTS reverse_charge BOOLEAN NOT NULL DEFAULT false;

-- 5. Seller (Nxtgauge) details
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS seller_name VARCHAR(255) NOT NULL DEFAULT 'Nxtgauge Technologies Pvt. Ltd.',
    ADD COLUMN IF NOT EXISTS seller_address TEXT NOT NULL DEFAULT '',
    ADD COLUMN IF NOT EXISTS seller_gstin VARCHAR(15),
    ADD COLUMN IF NOT EXISTS seller_pan VARCHAR(10),
    ADD COLUMN IF NOT EXISTS seller_state_code VARCHAR(2);

-- 6. Customer billing details (snapshot at the time of issue)
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS customer_name VARCHAR(255),
    ADD COLUMN IF NOT EXISTS customer_email VARCHAR(255),
    ADD COLUMN IF NOT EXISTS customer_phone VARCHAR(20),
    ADD COLUMN IF NOT EXISTS customer_billing_address TEXT,
    ADD COLUMN IF NOT EXISTS customer_gstin VARCHAR(15),
    ADD COLUMN IF NOT EXISTS customer_state_code VARCHAR(2);

-- 7. Discount / adjustment fields
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS discount_amount INTEGER NOT NULL DEFAULT 0,
    ADD COLUMN IF NOT EXISTS discount_label VARCHAR(255),
    ADD COLUMN IF NOT EXISTS notes TEXT;

-- 8. Lifecycle timestamps
ALTER TABLE invoices
    ADD COLUMN IF NOT EXISTS paid_at TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS voided_at TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS voided_by_user_id UUID REFERENCES users(id),
    ADD COLUMN IF NOT EXISTS void_reason TEXT,
    ADD COLUMN IF NOT EXISTS pdf_object_key VARCHAR(500),
    ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW();

-- Backfill `updated_at` on existing rows.
UPDATE invoices SET updated_at = COALESCE(updated_at, issued_at, NOW());

-- 9. CHECKs
ALTER TABLE invoices
    DROP CONSTRAINT IF EXISTS invoices_amounts_nonneg;
ALTER TABLE invoices
    ADD CONSTRAINT invoices_amounts_nonneg
    CHECK (
        subtotal >= 0
        AND gst_amount >= 0
        AND total >= 0
        AND cgst_amount >= 0
        AND sgst_amount >= 0
        AND igst_amount >= 0
        AND discount_amount >= 0
    );

ALTER TABLE invoices
    DROP CONSTRAINT IF EXISTS invoices_total_matches;
ALTER TABLE invoices
    ADD CONSTRAINT invoices_total_matches
    CHECK (total = subtotal - discount_amount + gst_amount);

-- 10. Line items
CREATE TABLE IF NOT EXISTS invoice_line_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    invoice_id UUID NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
    line_number INTEGER NOT NULL,
    description TEXT NOT NULL,
    hsn_sac_code VARCHAR(20),
    quantity NUMERIC(12,3) NOT NULL DEFAULT 1,
    unit_price_inr INTEGER NOT NULL,
    line_subtotal_inr INTEGER NOT NULL,
    tax_rate NUMERIC(5,2) NOT NULL DEFAULT 0,
    line_tax_inr INTEGER NOT NULL DEFAULT 0,
    line_total_inr INTEGER NOT NULL,
    metadata JSONB,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(invoice_id, line_number)
);
CREATE INDEX IF NOT EXISTS idx_invoice_line_items_invoice
    ON invoice_line_items(invoice_id);

-- 11. Customer billing profiles
CREATE TABLE IF NOT EXISTS billing_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    legal_name VARCHAR(255) NOT NULL,
    email VARCHAR(255),
    phone VARCHAR(20),
    gstin VARCHAR(15),
    pan VARCHAR(10),
    billing_address TEXT NOT NULL,
    state_code VARCHAR(2),
    is_default BOOLEAN NOT NULL DEFAULT false,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_billing_profiles_user
    ON billing_profiles(user_id);
-- At most one default per user
CREATE UNIQUE INDEX IF NOT EXISTS uq_billing_profiles_default_per_user
    ON billing_profiles(user_id)
    WHERE is_default = true;

-- 12. Invoice sequence for human-readable numbers
CREATE SEQUENCE IF NOT EXISTS invoice_number_seq START 100000;

-- 13. Indexes on invoices
CREATE INDEX IF NOT EXISTS idx_invoices_status_issued_at
    ON invoices(status, issued_at DESC);
CREATE INDEX IF NOT EXISTS idx_invoices_payment_id
    ON invoices(payment_id);
