import { DataTypes } from 'sequelize';
import { createIndexIfNotExists, safeApplyColumnChanges, type Migration } from '../migrate';
import models from '../models';

export const up: Migration = async ({ context }) => {
  // 1. Customer: per-channel UUID for IAP appAccountToken / obfuscatedAccountId mapping (D-004)
  await safeApplyColumnChanges(context, {
    customers: [
      { name: 'app_store_uuid', field: { type: DataTypes.STRING(36), allowNull: true } },
      { name: 'google_play_uuid', field: { type: DataTypes.STRING(36), allowNull: true } },
    ],
  });
  // SQLite/D1 allows multiple NULLs in UNIQUE columns, so a plain UNIQUE index
  // is functionally equivalent to a partial one (WHERE col IS NOT NULL).
  await createIndexIfNotExists(context, 'customers', ['app_store_uuid'], 'idx_customers_app_store_uuid', {
    unique: true,
  });
  await createIndexIfNotExists(context, 'customers', ['google_play_uuid'], 'idx_customers_google_play_uuid', {
    unique: true,
  });

  // 2. Subscription: channel + environment (D-005)
  await safeApplyColumnChanges(context, {
    subscriptions: [
      { name: 'channel', field: { type: DataTypes.STRING(20), allowNull: true } },
      {
        name: 'environment',
        field: { type: DataTypes.STRING(20), allowNull: true, defaultValue: 'production' },
      },
    ],
  });

  // 3. Invoice: three-segment amounts for cross-channel accounting (D-001 A)
  await safeApplyColumnChanges(context, {
    invoices: [
      { name: 'gross_amount', field: { type: DataTypes.STRING(32), allowNull: true } },
      { name: 'platform_fee', field: { type: DataTypes.STRING(32), defaultValue: '0' } },
      { name: 'net_amount', field: { type: DataTypes.STRING(32), allowNull: true } },
    ],
  });
  // Backfill: existing Stripe / on-chain rows have no platform fee, so gross = net = total
  await context.sequelize.query(
    'UPDATE invoices SET gross_amount = total, net_amount = total WHERE gross_amount IS NULL'
  );

  // 4. Refund: source (merchant_initiated | platform_initiated)
  await safeApplyColumnChanges(context, {
    refunds: [
      {
        name: 'source',
        field: { type: DataTypes.STRING(30), allowNull: true, defaultValue: 'merchant_initiated' },
      },
    ],
  });

  // 5. Entitlement tables (D-003 B)
  await context.createTable('entitlements', models.Entitlement.GENESIS_ATTRIBUTES);
  await createIndexIfNotExists(context, 'entitlements', ['key'], 'idx_entitlements_key', { unique: true });

  await context.createTable('entitlement_products', models.EntitlementProduct.GENESIS_ATTRIBUTES);

  await context.createTable('entitlement_grants', models.EntitlementGrant.GENESIS_ATTRIBUTES);
  await createIndexIfNotExists(
    context,
    'entitlement_grants',
    ['customer_id', 'entitlement_id', 'status'],
    'idx_entitlement_grants_lookup'
  );
  await createIndexIfNotExists(
    context,
    'entitlement_grants',
    ['source_subscription_id'],
    'idx_entitlement_grants_source_sub'
  );

  // Note: PaymentMethod.type ENUM extension to include 'app_store' / 'google_play'
  // is intentionally NOT changed at DB level — on D1/SQLite the column is already TEXT
  // with no CHECK constraint, so any value is accepted. The model-level type union
  // is updated in models/payment-method.ts when A1/A2 lands.
};

export const down: Migration = async ({ context }) => {
  await context.removeIndex('entitlement_grants', 'idx_entitlement_grants_source_sub');
  await context.removeIndex('entitlement_grants', 'idx_entitlement_grants_lookup');
  await context.dropTable('entitlement_grants');

  await context.dropTable('entitlement_products');

  await context.removeIndex('entitlements', 'idx_entitlements_key');
  await context.dropTable('entitlements');

  await context.removeColumn('refunds', 'source');

  await context.removeColumn('invoices', 'net_amount');
  await context.removeColumn('invoices', 'platform_fee');
  await context.removeColumn('invoices', 'gross_amount');

  await context.removeColumn('subscriptions', 'environment');
  await context.removeColumn('subscriptions', 'channel');

  await context.removeIndex('customers', 'idx_customers_google_play_uuid');
  await context.removeIndex('customers', 'idx_customers_app_store_uuid');
  await context.removeColumn('customers', 'google_play_uuid');
  await context.removeColumn('customers', 'app_store_uuid');
};
