import {
  Sequelize,
  DataTypes,
  Model,
  InferAttributes,
  InferCreationAttributes,
  CreationOptional,
} from "sequelize";
import type {
  ElectionSecurityEventType,
  ElectionSecurityReviewStatus,
} from "@/types";
import { parseJsonColumn } from "@/lib/utils/parse-json-column";

export class ElectionSecurityEvent extends Model<
  InferAttributes<ElectionSecurityEvent>,
  InferCreationAttributes<ElectionSecurityEvent>
> {
  declare id: CreationOptional<string>;
  declare electionId: string;
  declare voterRollId: string | null;
  declare eventType: ElectionSecurityEventType;
  declare ipHash: string | null;
  declare deviceFingerprintHash: string | null;
  declare detail: Record<string, unknown> | null;
  declare reviewedByUserId: string | null;
  declare reviewStatus: CreationOptional<ElectionSecurityReviewStatus>;
  declare createdAt: CreationOptional<Date>;
  declare updatedAt: CreationOptional<Date>;
}

export function initElectionSecurityEventModel(sequelize: Sequelize) {
  ElectionSecurityEvent.init(
    {
      id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        primaryKey: true,
      },
      electionId: { type: DataTypes.UUID, allowNull: false },
      voterRollId: { type: DataTypes.UUID, allowNull: true },
      eventType: {
        type: DataTypes.ENUM(
          "duplicate_attempt",
          "invalid_authorization_block",
          "device_reuse_flag",
          "ai_anomaly_flag"
        ),
        allowNull: false,
      },
      ipHash: { type: DataTypes.STRING(64), allowNull: true },
      deviceFingerprintHash: { type: DataTypes.STRING(64), allowNull: true },
      detail: {
        type: DataTypes.JSON,
        allowNull: true,
        get() {
          return parseJsonColumn<Record<string, unknown>>(
            this.getDataValue("detail")
          );
        },
        set(value: Record<string, unknown> | string | null) {
          this.setDataValue(
            "detail",
            typeof value === "string"
              ? parseJsonColumn<Record<string, unknown>>(value)
              : value
          );
        },
      },
      reviewedByUserId: { type: DataTypes.UUID, allowNull: true },
      reviewStatus: {
        type: DataTypes.ENUM("open", "dismissed", "confirmed_fraud"),
        allowNull: false,
        defaultValue: "open",
      },
      createdAt: DataTypes.DATE,
      updatedAt: DataTypes.DATE,
    },
    {
      sequelize,
      modelName: "ElectionSecurityEvent",
      tableName: "ElectionSecurityEvents",
    }
  );
  return ElectionSecurityEvent;
}
