import { MigrationInterface, QueryRunner } from 'typeorm';

/**
 * Payment Collections — customer-centric collection events that
 * allocate a single received amount across multiple settlements
 * (across multiple bookings + service types) for one customer.
 *
 * Existing model (PaymentSettlementService.recordPayment) is per-
 * settlement: one payment → one settlement → one service item. The
 * new flow groups N allocations under one parent so finance can
 * tell a customer "you paid 5,000 AED on 12 Jun, here's how it was
 * spread across your three bookings".
 *
 * Schema choices:
 *   - Customer key is `customer_mobile` (Phase 1 has no Customer
 *     Master — stakeholder-locked 2026-06-13). `customer_name` is
 *     snapshotted so historical receipts stay readable even if the
 *     guest record changes downstream.
 *   - Same-currency only per collection (`currency_id` REQUIRED) —
 *     also stakeholder-locked. Cross-currency requires FX rules
 *     we don't want to retrofit later.
 *   - `settlement_payments.collection_id` is nullable so legacy
 *     per-settlement payments (recorded via the Settle dialog) keep
 *     working unchanged. New collect-flow payments carry the link.
 *   - One receipt_no per collection event — all N child
 *     settlement_payment rows inherit it from the parent.
 *
 * Excess handling:
 *   - `excess_amount` ≥ 0 (default 0) — set when received_amount
 *     exceeds the sum of allocations.
 *   - `excess_treatment` ∈ {'CREDIT','ADVANCE'} or NULL when no
 *     excess. Phase D adds the customer_credit_ledger that draws
 *     from this. For now the value is stored as intent only.
 */
export class PaymentCollections1781300000000 implements MigrationInterface {
  name = 'PaymentCollections1781300000000';

  public async up(qr: QueryRunner): Promise<void> {
    await qr.query(`
      CREATE TABLE payment_collections (
        id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
        tenant_id uuid NOT NULL,
        receipt_no varchar(20) NOT NULL,
        receipt_year integer NOT NULL,
        customer_mobile varchar(20) NOT NULL,
        customer_name varchar(200),
        payment_date date NOT NULL,
        mode varchar(32) NOT NULL,
        ref_no varchar(100),
        currency_id uuid NOT NULL REFERENCES currencies(id),
        received_amount numeric(12,2) NOT NULL,
        allocated_amount numeric(12,2) NOT NULL DEFAULT 0,
        excess_amount numeric(12,2) NOT NULL DEFAULT 0,
        excess_treatment varchar(16),
        notes text,
        is_void boolean NOT NULL DEFAULT false,
        voided_at timestamptz,
        voided_by uuid,
        void_reason text,
        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 payment_collections_received_positive CHECK (received_amount > 0),
        CONSTRAINT payment_collections_allocated_nonneg CHECK (allocated_amount >= 0),
        CONSTRAINT payment_collections_excess_nonneg CHECK (excess_amount >= 0),
        CONSTRAINT payment_collections_allocated_le_received
          CHECK (allocated_amount <= received_amount + 0.005),
        CONSTRAINT payment_collections_excess_treatment_valid
          CHECK (excess_treatment IS NULL OR excess_treatment IN ('CREDIT','ADVANCE'))
      );
    `);

    await qr.query(`
      CREATE INDEX idx_payment_collections_tenant_mobile_date
        ON payment_collections (tenant_id, customer_mobile, payment_date DESC);
    `);
    await qr.query(`
      CREATE INDEX idx_payment_collections_tenant_date
        ON payment_collections (tenant_id, payment_date DESC);
    `);
    await qr.query(`
      CREATE UNIQUE INDEX uq_payment_collections_tenant_receipt
        ON payment_collections (tenant_id, receipt_year, receipt_no);
    `);

    await qr.query(`
      ALTER TABLE settlement_payments
        ADD COLUMN collection_id uuid REFERENCES payment_collections(id) ON DELETE SET NULL;
    `);
    await qr.query(`
      CREATE INDEX idx_settlement_payments_collection
        ON settlement_payments (tenant_id, collection_id);
    `);
  }

  public async down(qr: QueryRunner): Promise<void> {
    await qr.query(`DROP INDEX IF EXISTS idx_settlement_payments_collection;`);
    await qr.query(`ALTER TABLE settlement_payments DROP COLUMN IF EXISTS collection_id;`);
    await qr.query(`DROP INDEX IF EXISTS uq_payment_collections_tenant_receipt;`);
    await qr.query(`DROP INDEX IF EXISTS idx_payment_collections_tenant_date;`);
    await qr.query(`DROP INDEX IF EXISTS idx_payment_collections_tenant_mobile_date;`);
    await qr.query(`DROP TABLE IF EXISTS payment_collections;`);
  }
}
