const { DataTypes } = require('sequelize');
const { generateTransactionId } = require('../utils/helpers');

module.exports = (sequelize) => {
  const Transaction = sequelize.define(
    "Transaction",
    {
      id: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
      },

      transactionId: {
        type: DataTypes.STRING(50),
        allowNull: false,
        unique: true,
        defaultValue: () => generateTransactionId(),
        field: "transaction_id",
      },

      userId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: false,
        field: "user_id",
        references: {
          model: 'users',
          key: 'id',
        },
      },

      source: {
        type: DataTypes.ENUM('funding', 'wallet','derivatives'), // funding | wallet
        allowNull: false,
      },

      toType: {
        type: DataTypes.ENUM('internal', 'external'), // internal | external
        allowNull: false,
        field: "to_type",
      },

      kind: {
        type: DataTypes.ENUM(
          'deposit','withdrawal','transfer_in','transfer_out','bonus','swap','staking','signal','bot','trade_profit','spot','forex','terminal','stock','options','fee','referral_bonus','staking_reward','savings_interest','launchpad_purchase','investment','roi','airdrop','adjustment','derivative_deposit','derivative_withdrawal'
        ),
        allowNull: false,
      },

      direction: {
        type: DataTypes.ENUM('credit', 'debit'), // credit | debit
        allowNull: false,
      },

      currency: {
        type: DataTypes.STRING(20),
        allowNull: false,
      },

      amount: {
        type: DataTypes.DECIMAL(30, 18),
        allowNull: false,
        defaultValue: 0,
      },

      fee: {
        type: DataTypes.DECIMAL(30, 18),
        allowNull: false,
        defaultValue: 0,
      },

      feeCurrency: {
        type: DataTypes.STRING(20),
        allowNull: true,
        field: "fee_currency",
      },

      netAmount: {
        type: DataTypes.DECIMAL(30, 18),
        allowNull: true,
        field: "net_amount",
      },
      planId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: true,
        field: "plan_id",
      },
      methodId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: true,
        field: "method_id",
      },

      walletId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: true,
        field: "wallet_id",
      },

      fromWalletId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: true,
        field: "from_wallet_id",
      },




      toWalletId: {
        type: DataTypes.BIGINT.UNSIGNED,
        allowNull: true,
        field: "to_wallet_id",
      },

      network: { type: DataTypes.STRING(50), allowNull: true },
      address: { type: DataTypes.STRING(255), allowNull: true },

      txHash: { type: DataTypes.STRING(255), allowNull: true, field: "tx_hash" },

      confirmations: { type: DataTypes.INTEGER, allowNull: false, defaultValue: 0 },
      requiredConfirmations: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 0,
        field: "required_confirmations",
      },

      orderId: { type: DataTypes.BIGINT.UNSIGNED, allowNull: true, field: "order_id" },
      tradePair: { type: DataTypes.STRING(20), allowNull: true, field: "trade_pair" },
      price: { type: DataTypes.DECIMAL(30, 18), allowNull: true },
      quantity: { type: DataTypes.DECIMAL(30, 18), allowNull: true },

      balanceBefore: { type: DataTypes.DECIMAL(30, 18), allowNull: true, field: "balance_before" },
      balanceAfter: { type: DataTypes.DECIMAL(30, 18), allowNull: true, field: "balance_after" },

      status: {
        type: DataTypes.ENUM('initiated','pending', 'processing', 'completed', 'failed', 'cancelled'),
        allowNull: false, defaultValue: "pending"
      },

      createdAt: { type: DataTypes.DATE, field: "created_at" },
      updatedAt: { type: DataTypes.DATE, field: "updated_at" },

      processedAt: { type: DataTypes.DATE, allowNull: true, field: "processed_at" },
      completedAt: { type: DataTypes.DATE, allowNull: true, field: "completed_at" },
      failedAt: { type: DataTypes.DATE, allowNull: true, field: "failed_at" },
      cancelledAt: { type: DataTypes.DATE, allowNull: true, field: "cancelled_at" },

      errorMessage: { type: DataTypes.TEXT, allowNull: true, field: "error_message" },
      errorCode: { type: DataTypes.STRING(50), allowNull: true, field: "error_code" },

      description: { type: DataTypes.TEXT, allowNull: true },
      notes: { type: DataTypes.TEXT, allowNull: true },

      ip: { type: DataTypes.STRING(45), allowNull: true },
      device: { type: DataTypes.STRING(255), allowNull: true },

      metadata: {
        type: DataTypes.JSON,
        allowNull: false,
        defaultValue: {},
      },
    },
    {
      tableName: "transactions",
      underscored: true,
      timestamps: true,
      hooks: {
        beforeSave: (transaction) => {
          if (transaction.amount !== undefined && transaction.fee !== undefined) {
            transaction.netAmount = parseFloat(transaction.amount) - parseFloat(transaction.fee);
          }
        },
      },
    }
  );

  Transaction.associate = (models) => {
    Transaction.belongsTo(models.User, { foreignKey: "userId", as: "user" });
  };

  return Transaction;
};
