import {
  MigrationInterface,
  QueryRunner,
  Table,
  TableColumn,
  TableForeignKey,
} from "typeorm"

export class AddSubscriptionSystem1776770373342 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    // 1. Add activation_token column to users table
    await queryRunner.addColumn(
      "users",
      new TableColumn({
        name: "activation_token",
        type: "varchar",
        length: "255",
        isNullable: true,
      }),
    )

    // 2. Create stripe_settings table (admin-managed Stripe keys)
    await queryRunner.createTable(
      new Table({
        name: "stripe_settings",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "stripe_secret_key",
            type: "text",
            isNullable: false,
          },
          {
            name: "stripe_publishable_key",
            type: "text",
            isNullable: false,
          },
          {
            name: "is_active",
            type: "tinyint",
            default: 1,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
          {
            name: "updated_at",
            type: "timestamp",
            isNullable: true,
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 3. Create subscription_plans table
    await queryRunner.createTable(
      new Table({
        name: "subscription_plans",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "name",
            type: "varchar",
            length: "255",
            isNullable: false,
          },
          {
            name: "description",
            type: "text",
            isNullable: true,
          },
          {
            name: "price",
            type: "decimal",
            precision: 10,
            scale: 2,
            isNullable: true,
          },
          {
            name: "currency",
            type: "varchar",
            length: "10",
            isNullable: true,
            default: "'usd'",
          },
          {
            name: "interval",
            type: "varchar",
            length: "20",
            isNullable: true,
            default: "'month'",
          },
          {
            name: "interval_count",
            type: "int",
            isNullable: true,
            default: 1,
          },
          {
            name: "features",
            type: "text",
            isNullable: true,
          },
          {
            name: "stripe_price_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "stripe_product_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "is_active",
            type: "tinyint",
            isNullable: true,
            default: 1,
          },
          {
            name: "sort_order",
            type: "int",
            isNullable: true,
            default: 0,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
          {
            name: "updated_at",
            type: "timestamp",
            isNullable: true,
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 4. Create subscriptions table
    await queryRunner.createTable(
      new Table({
        name: "subscriptions",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "user_id",
            type: "bigint",
            unsigned: true,
            isNullable: false,
          },
          {
            name: "plan_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "status",
            type: "varchar",
            length: "50",
            default: "'trialing'",
          },
          {
            name: "stripe_customer_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "stripe_subscription_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "trial_start",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "trial_end",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "current_period_start",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "current_period_end",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "cancel_at_period_end",
            type: "tinyint",
            default: 0,
          },
          {
            name: "cancelled_at",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "next_plan_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "next_plan_start_date",
            type: "timestamp",
            isNullable: true,
          },
          {
            name: "next_stripe_subscription_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
          {
            name: "updated_at",
            type: "timestamp",
            isNullable: true,
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 5. Create transactions table
    await queryRunner.createTable(
      new Table({
        name: "transactions",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "user_id",
            type: "bigint",
            unsigned: true,
            isNullable: false,
          },
          {
            name: "subscription_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "plan_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "plan_name",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "amount",
            type: "decimal",
            precision: 10,
            scale: 2,
            isNullable: false,
          },
          {
            name: "currency",
            type: "varchar",
            length: "10",
            default: "'usd'",
          },
          {
            name: "status",
            type: "varchar",
            length: "50",
            default: "'pending'",
          },
          {
            name: "stripe_payment_intent_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "stripe_invoice_id",
            type: "varchar",
            length: "255",
            isNullable: true,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
          {
            name: "updated_at",
            type: "timestamp",
            isNullable: true,
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 6. Create webhook_logs table
    await queryRunner.createTable(
      new Table({
        name: "webhook_logs",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "event_id",
            type: "varchar",
            length: "255",
            isNullable: false,
          },
          {
            name: "type",
            type: "varchar",
            length: "100",
            isNullable: false,
          },
          {
            name: "payload",
            type: "longtext",
            isNullable: true,
          },
          {
            name: "status",
            type: "varchar",
            length: "50",
            default: "'received'",
          },
          {
            name: "error_message",
            type: "text",
            isNullable: true,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 7. Create subscription_history table
    await queryRunner.createTable(
      new Table({
        name: "subscription_history",
        columns: [
          {
            name: "id",
            type: "bigint",
            unsigned: true,
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "user_id",
            type: "bigint",
            unsigned: true,
            isNullable: false,
          },
          {
            name: "old_plan_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "new_plan_id",
            type: "bigint",
            unsigned: true,
            isNullable: true,
          },
          {
            name: "action",
            type: "varchar",
            length: "50",
            isNullable: false,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
        ],
        engine: "InnoDB",
      }),
    )

    // 8. Add foreign keys for subscription_history
    await queryRunner.createForeignKey(
      "subscription_history",
      new TableForeignKey({
        columnNames: ["user_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "users",
        onDelete: "CASCADE",
      }),
    )

    await queryRunner.createForeignKey(
      "subscription_history",
      new TableForeignKey({
        columnNames: ["old_plan_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscription_plans",
        onDelete: "SET NULL",
      }),
    )

    await queryRunner.createForeignKey(
      "subscription_history",
      new TableForeignKey({
        columnNames: ["new_plan_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscription_plans",
        onDelete: "SET NULL",
      }),
    )

    // 9. Add foreign keys for subscriptions
    await queryRunner.createForeignKey(
      "subscriptions",
      new TableForeignKey({
        columnNames: ["user_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "users",
        onDelete: "CASCADE",
      }),
    )

    await queryRunner.createForeignKey(
      "subscriptions",
      new TableForeignKey({
        columnNames: ["plan_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscription_plans",
        onDelete: "SET NULL",
      }),
    )

    await queryRunner.createForeignKey(
      "subscriptions",
      new TableForeignKey({
        columnNames: ["next_plan_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscription_plans",
        onDelete: "SET NULL",
      }),
    )

    // 10. Add foreign keys for transactions
    await queryRunner.createForeignKey(
      "transactions",
      new TableForeignKey({
        columnNames: ["user_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "users",
        onDelete: "CASCADE",
      }),
    )

    await queryRunner.createForeignKey(
      "transactions",
      new TableForeignKey({
        columnNames: ["subscription_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscriptions",
        onDelete: "SET NULL",
      }),
    )

    await queryRunner.createForeignKey(
      "transactions",
      new TableForeignKey({
        columnNames: ["plan_id"],
        referencedColumnNames: ["id"],
        referencedTableName: "subscription_plans",
        onDelete: "SET NULL",
      }),
    )
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    const subscriptionHistoryTable = await queryRunner.getTable(
      "subscription_history",
    )
    if (subscriptionHistoryTable) {
      for (const fk of subscriptionHistoryTable.foreignKeys) {
        await queryRunner.dropForeignKey("subscription_history", fk)
      }
    }

    const transactionsTable = await queryRunner.getTable("transactions")
    if (transactionsTable) {
      for (const fk of transactionsTable.foreignKeys) {
        await queryRunner.dropForeignKey("transactions", fk)
      }
    }

    const subscriptionsTable = await queryRunner.getTable("subscriptions")
    if (subscriptionsTable) {
      for (const fk of subscriptionsTable.foreignKeys) {
        await queryRunner.dropForeignKey("subscriptions", fk)
      }
    }

    await queryRunner.dropTable("subscription_history")
    await queryRunner.dropTable("webhook_logs")
    await queryRunner.dropTable("transactions")
    await queryRunner.dropTable("subscriptions")
    await queryRunner.dropTable("subscription_plans")
    await queryRunner.dropTable("stripe_settings")
    await queryRunner.dropColumn("users", "activation_token")
  }
}
