-- 062: Crypto payment ledger — immutable money ledger
--
-- Every crypto→USD movement writes one row here: the initial SHKeeper
-- receive, any mid-path swaps (e.g. ETH→USDC), the Coinbase Prime
-- offramp, the Relay bank deposit, card authorizations + settlements,
-- and cold-wallet sweeps. Rows are never mutated after creation —
-- corrections use a `movement_type='adjustment'` or `'reversal'` entry
-- that links via related_ledger_id.
--
-- This table is the source of truth for IRS Form 8949 cost-basis
-- reconciliation: every `receive` captures acquired_at + fx_rate_usd
-- (cost basis); every `offramp` captures disposed_at + proceeds_usd.

CREATE TABLE IF NOT EXISTS crypto_payment_ledger (
    id                   BIGSERIAL PRIMARY KEY,
    order_id             TEXT NOT NULL,
    order_type           TEXT NOT NULL,             -- compliance | formation | canada_crtc | bundle
    coin                 TEXT NOT NULL,             -- BTC | ETH | MATIC | LTC | TRX | BNB | DOGE | USDC | USD
    movement_type        TEXT NOT NULL CHECK (movement_type IN (
        'receive',              -- customer → SHKeeper (ledger entry on webhook confirm)
        'swap',                 -- within exchange, coin → coin (e.g., ETH → USDC)
        'offramp',              -- coin → USD via Coinbase Prime market-sell
        'bank_deposit',         -- USD arrival at RelayFi (matched from IMAP monitor)
        'card_authorization',   -- Relay debit card auth event (card_settlement follows)
        'card_settlement',      -- Relay debit card final posting
        'sweep',                -- hot → cold wallet transfer
        'reversal',             -- corrective entry undoing a prior row
        'adjustment'            -- manual accounting correction
    )),
    amount_coin          NUMERIC(36,18),            -- signed; +in, -out. NULL for USD-only rows.
    amount_usd_cents     BIGINT NOT NULL,           -- signed USD-equivalent at entry time
    fx_rate_usd          NUMERIC(24,10),            -- coin→USD rate captured at entry
    basis_usd_cents      BIGINT,                    -- cost basis for disposal rows (FIFO)
    proceeds_usd_cents   BIGINT,                    -- proceeds for disposal rows
    acquired_at          TIMESTAMPTZ,               -- when this coin was originally received (receive rows)
    disposed_at          TIMESTAMPTZ,               -- when this coin was sold (offramp rows)
    provider             TEXT,                      -- shkeeper | coinbase_prime | relay
    provider_ref         TEXT,                      -- tx hash | Prime order id | Relay tx id
    provider_status      TEXT,
    state                TEXT NOT NULL DEFAULT 'pending'
                         CHECK (state IN ('pending','confirmed','failed','reversed')),
    idempotency_key      TEXT UNIQUE,               -- e.g. "shkeeper:<txid>" | "prime:<order>" | "sweep:<id>"
    related_ledger_id    BIGINT REFERENCES crypto_payment_ledger(id),
    notes                TEXT,
    created_at           TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at           TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_cpl_order        ON crypto_payment_ledger (order_id);
CREATE INDEX IF NOT EXISTS idx_cpl_pending      ON crypto_payment_ledger (state) WHERE state = 'pending';
CREATE INDEX IF NOT EXISTS idx_cpl_disposal     ON crypto_payment_ledger (disposed_at) WHERE disposed_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_cpl_movement_type ON crypto_payment_ledger (movement_type);
CREATE INDEX IF NOT EXISTS idx_cpl_provider_ref ON crypto_payment_ledger (provider, provider_ref) WHERE provider_ref IS NOT NULL;
