const { DataTypes } = require('sequelize');
const { generateApiKey, generateApiSecret } = require('../utils/helpers');

module.exports = (sequelize) => {
  const ApiKey = sequelize.define('ApiKey', {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      primaryKey: true,
    },
    userId: {
      type: DataTypes.BIGINT.UNSIGNED,
      allowNull: false,
      field: 'user_id',
      references: {
        model: 'users',
        key: 'id',
      },
    },
    name: {
      type: DataTypes.STRING(100),
      allowNull: false,
    },
    key: {
      type: DataTypes.STRING(100),
      unique: true,
      defaultValue: () => generateApiKey(),
    },
    secret: {
      type: DataTypes.STRING(100),
      defaultValue: () => generateApiSecret(),
    },
    secretHash: {
      type: DataTypes.STRING(255),
      field: 'secret_hash',
    },
    permissions: {
      type: DataTypes.JSON,
      defaultValue: {
        read: true,
        trade: false,
        withdraw: false,
      },
    },
    ipRestrictions: {
      type: DataTypes.JSON,
      defaultValue: [],
      field: 'ip_restrictions',
    },
    status: {
      type: DataTypes.ENUM('active', 'inactive', 'revoked'),
      defaultValue: 'active',
    },
    lastUsedAt: {
      type: DataTypes.DATE,
      field: 'last_used_at',
    },
    lastUsedIp: {
      type: DataTypes.STRING(45),
      field: 'last_used_ip',
    },
    expiresAt: {
      type: DataTypes.DATE,
      field: 'expires_at',
    },
    revokedAt: {
      type: DataTypes.DATE,
      field: 'revoked_at',
    },
    metadata: {
      type: DataTypes.JSON,
      defaultValue: {},
    },
  }, {
    tableName: 'api_keys',
    timestamps: true,
    underscored: true,
    indexes: [
      { fields: ['user_id'] },
      { fields: ['key'] },
      { fields: ['status'] },
    ],
  });

  // Instance Methods
  ApiKey.prototype.revoke = async function () {
    this.status = 'revoked';
    this.revokedAt = new Date();
    return this.save();
  };

  ApiKey.prototype.updateUsage = async function (ip) {
    this.lastUsedAt = new Date();
    this.lastUsedIp = ip;
    return this.save();
  };

  ApiKey.prototype.hasPermission = function (permission) {
    return this.permissions && this.permissions[permission] === true;
  };

  ApiKey.prototype.isIpAllowed = function (ip) {
    if (!this.ipRestrictions || this.ipRestrictions.length === 0) {
      return true;
    }
    return this.ipRestrictions.includes(ip);
  };

  return ApiKey;
};