/* eslint-disable no-await-in-loop */
import { DataTypes } from 'sequelize';

import { Migration, safeApplyColumnChanges, createIndexIfNotExists } from '../migrate';

export const up: Migration = async ({ context }) => {
  // Add dynamic pricing fields to prices table
  await safeApplyColumnChanges(context, {
    prices: [
      {
        name: 'pricing_type',
        field: {
          type: DataTypes.ENUM('fixed', 'dynamic'),
          defaultValue: 'fixed',
          allowNull: false,
        },
      },
      {
        name: 'base_currency',
        field: {
          type: DataTypes.STRING(8),
          allowNull: true,
        },
      },
      {
        name: 'base_amount',
        field: {
          type: DataTypes.STRING(32),
          allowNull: true,
        },
      },
      {
        name: 'dynamic_pricing_config',
        field: {
          type: DataTypes.JSON,
          allowNull: true,
        },
      },
    ],
  });

  // Create exchange_rate_providers table
  const tables = await context.showAllTables();
  if (!tables.includes('exchange_rate_providers')) {
    await context.createTable('exchange_rate_providers', {
      id: {
        type: DataTypes.STRING(32),
        primaryKey: true,
        allowNull: false,
      },
      name: {
        type: DataTypes.STRING(64),
        allowNull: false,
        unique: true,
      },
      type: {
        type: DataTypes.STRING(32),
        allowNull: false,
        defaultValue: 'token-data',
      },
      enabled: {
        type: DataTypes.BOOLEAN,
        allowNull: false,
        defaultValue: true,
      },
      priority: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 1,
      },
      status: {
        type: DataTypes.ENUM('active', 'degraded', 'paused', 'inactive'),
        allowNull: false,
        defaultValue: 'active',
      },
      paused_reason: {
        type: DataTypes.STRING(512),
        allowNull: true,
      },
      config: {
        type: DataTypes.JSON,
        allowNull: true,
      },
      last_success_at: {
        type: DataTypes.DATE,
        allowNull: true,
      },
      last_failure_at: {
        type: DataTypes.DATE,
        allowNull: true,
      },
      failure_count: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0,
      },
      created_at: {
        type: DataTypes.DATE,
        defaultValue: DataTypes.NOW,
        allowNull: false,
      },
      updated_at: {
        type: DataTypes.DATE,
        defaultValue: DataTypes.NOW,
        allowNull: false,
      },
    });

    await createIndexIfNotExists(context, 'exchange_rate_providers', ['name'], 'idx_erp_name', {
      unique: true,
    });
    await createIndexIfNotExists(
      context,
      'exchange_rate_providers',
      ['enabled', 'priority'],
      'idx_erp_enabled_priority'
    );

    // Insert default token-data provider
    await context.bulkInsert('exchange_rate_providers', [
      {
        id: `erp_${Date.now()}`,
        name: 'token-data',
        type: 'token-data',
        enabled: true,
        priority: 1,
        status: 'active',
        config: JSON.stringify({ base_url: 'https://token-data.arcblock.io' }),
        failure_count: 0,
        created_at: new Date(),
        updated_at: new Date(),
      },
    ]);
  }

  // Create price_quotes table
  if (!tables.includes('price_quotes')) {
    await context.createTable('price_quotes', {
      id: {
        type: DataTypes.STRING(32),
        primaryKey: true,
        allowNull: false,
      },
      price_id: {
        type: DataTypes.STRING(32),
        allowNull: false,
      },
      session_id: {
        type: DataTypes.STRING(32),
        allowNull: true,
      },
      invoice_id: {
        type: DataTypes.STRING(32),
        allowNull: true,
      },
      idempotency_key: {
        type: DataTypes.STRING(128),
        allowNull: false,
        unique: true,
      },
      base_currency: {
        type: DataTypes.STRING(8),
        allowNull: false,
        defaultValue: 'USD',
      },
      base_amount: {
        type: DataTypes.STRING(32),
        allowNull: false,
      },
      target_currency_id: {
        type: DataTypes.STRING(16),
        allowNull: false,
      },
      rate_currency_symbol: {
        type: DataTypes.STRING(16),
        allowNull: false,
      },
      exchange_rate: {
        type: DataTypes.STRING(32),
        allowNull: false,
      },
      quoted_amount: {
        type: DataTypes.STRING(64),
        allowNull: false,
      },
      rate_provider_id: {
        type: DataTypes.STRING(32),
        allowNull: false,
      },
      rate_provider_name: {
        type: DataTypes.STRING(64),
        allowNull: false,
      },
      rate_timestamp_ms: {
        type: DataTypes.BIGINT,
        allowNull: false,
      },
      expires_at: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      status: {
        type: DataTypes.ENUM('active', 'used', 'paid', 'expired', 'cancelled', 'failed'),
        allowNull: false,
        defaultValue: 'active',
      },
      metadata: {
        type: DataTypes.JSON,
        allowNull: true,
      },
      created_at: {
        type: DataTypes.DATE,
        defaultValue: DataTypes.NOW,
        allowNull: false,
      },
    });

    await createIndexIfNotExists(context, 'price_quotes', ['idempotency_key'], 'idx_pq_idempotency', {
      unique: true,
    });
    await createIndexIfNotExists(
      context,
      'price_quotes',
      ['session_id', 'status', 'expires_at'],
      'idx_pq_session_status_expires'
    );
    await createIndexIfNotExists(context, 'price_quotes', ['invoice_id', 'status'], 'idx_pq_invoice_status');
    await createIndexIfNotExists(
      context,
      'price_quotes',
      ['rate_currency_symbol', 'created_at'],
      'idx_pq_currency_created'
    );
    await createIndexIfNotExists(context, 'price_quotes', ['created_at'], 'idx_pq_created');
  }
};

export const down: Migration = async ({ context }) => {
  await context.removeColumn('prices', 'pricing_type');
  await context.removeColumn('prices', 'base_currency');
  await context.removeColumn('prices', 'base_amount');
  await context.removeColumn('prices', 'dynamic_pricing_config');
  await context.dropTable('exchange_rate_providers');
  await context.dropTable('price_quotes');
};
