import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Phase D §12d — Customer / Agent credit ledger.
 *
 * When a collection's `received_amount` exceeds `allocated_amount` and
 * the user picks `excess_treatment = 'CREDIT'`, the leftover money is
 * parked here so the next time the same party pays, that credit can
 * auto-apply before they wire fresh money.
 *
 * Two parties share the same ledger schema:
 *   - CUSTOMER → party_key = the guest's mobile reduced to digits only
 *     (`normaliseMobileForLedger`), so "+91 98765-43210" and
 *     "+919876543210" resolve to one row. Phase 1 has no Customer
 *     Master (stakeholder-locked 2026-06-13); mobile beats name
 *     because two guests can share a name. The display name is
 *     snapshotted on `party_label`.
 *   - SOURCE   → party_key = trip_source uuid (stringified). This is
 *     the external "agent" (TravClan, MakeMyTrip, walk-in office)
 *     that channelled the booking and may wire us money on the
 *     customer's behalf — §12d "Agent mode".
 *
 * Balance is held per `(party_type, party_key, currency_id)`. Same-
 * currency policy is preserved end-to-end: cross-currency holding is
 * out of scope for Phase 1.
 *
 * `customer_credit_ledger_movements` is the immutable audit log of
 * every CREDIT (excess in) and DEBIT (applied to a new collection or
 * payout). The header table holds only the running balance; movements
 * answer "where did this 1,250 AED come from / go to".
 */
export class CustomerCreditLedger1782000000000 implements MigrationInterface {
  name = 'CustomerCreditLedger1782000000000';

  public async up(qr: QueryRunner): Promise<void> {
    await qr.query(`
      CREATE TABLE customer_credit_ledger (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        tenant_id uuid NOT NULL,
        party_type varchar(16) NOT NULL,
        party_key varchar(200) NOT NULL,
        party_label varchar(200) NOT NULL,
        currency_id uuid NOT NULL REFERENCES currencies(id),
        balance numeric(12,2) NOT NULL DEFAULT 0,
        last_collection_id uuid REFERENCES payment_collections(id),
        is_deleted boolean NOT NULL DEFAULT false,
        created_by uuid,
        updated_by uuid,
        created_at timestamptz NOT NULL DEFAULT now(),
        updated_at timestamptz NOT NULL DEFAULT now(),
        CONSTRAINT customer_credit_ledger_party_type_valid
          CHECK (party_type IN ('CUSTOMER','SOURCE')),
        CONSTRAINT customer_credit_ledger_balance_nonneg
          CHECK (balance >= 0)
      );
    `);

    await qr.query(`
      CREATE UNIQUE INDEX uq_customer_credit_ledger_party_currency
        ON customer_credit_ledger (tenant_id, party_type, party_key, currency_id)
        WHERE is_deleted = false;
    `);
    await qr.query(`
      CREATE INDEX idx_customer_credit_ledger_party
        ON customer_credit_ledger (tenant_id, party_type, party_key);
    `);

    await qr.query(`
      CREATE TABLE customer_credit_ledger_movements (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        tenant_id uuid NOT NULL,
        ledger_id uuid NOT NULL REFERENCES customer_credit_ledger(id) ON DELETE CASCADE,
        direction varchar(8) NOT NULL,
        amount numeric(12,2) NOT NULL,
        balance_after numeric(12,2) NOT NULL,
        collection_id uuid REFERENCES payment_collections(id) ON DELETE SET NULL,
        settlement_payment_id uuid REFERENCES settlement_payments(id) ON DELETE SET NULL,
        notes text,
        created_by uuid,
        created_at timestamptz NOT NULL DEFAULT now(),
        CONSTRAINT customer_credit_ledger_movements_direction_valid
          CHECK (direction IN ('CREDIT','DEBIT')),
        CONSTRAINT customer_credit_ledger_movements_amount_positive
          CHECK (amount > 0),
        CONSTRAINT customer_credit_ledger_movements_balance_nonneg
          CHECK (balance_after >= 0)
      );
    `);

    await qr.query(`
      CREATE INDEX idx_customer_credit_ledger_movements_ledger
        ON customer_credit_ledger_movements (tenant_id, ledger_id, created_at DESC);
    `);
  }

  public async down(qr: QueryRunner): Promise<void> {
    await qr.query(`DROP INDEX IF EXISTS idx_customer_credit_ledger_movements_ledger;`);
    await qr.query(`DROP TABLE IF EXISTS customer_credit_ledger_movements;`);
    await qr.query(`DROP INDEX IF EXISTS idx_customer_credit_ledger_party;`);
    await qr.query(`DROP INDEX IF EXISTS uq_customer_credit_ledger_party_currency;`);
    await qr.query(`DROP TABLE IF EXISTS customer_credit_ledger;`);
  }
}
