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

export class ParticipantConsentRecord extends Model<
  InferAttributes<ParticipantConsentRecord>,
  InferCreationAttributes<ParticipantConsentRecord>
> {
  declare id: CreationOptional<string>;
  declare participantProfileId: string;
  declare consentPolicyId: string;
  declare status: ConsentStatus;
  declare grantedAt: CreationOptional<Date | null>;
  declare withdrawnAt: CreationOptional<Date | null>;
  declare source: string;
  declare ipHash: CreationOptional<string | null>;
  declare userAgent: CreationOptional<string | null>;
  declare evidence: CreationOptional<Record<string, unknown> | null>;
  declare createdAt: CreationOptional<Date>;
  declare updatedAt: CreationOptional<Date>;
}

export function initParticipantConsentRecordModel(sequelize: Sequelize) {
  ParticipantConsentRecord.init(
    {
      id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        primaryKey: true,
      },
      participantProfileId: { type: DataTypes.UUID, allowNull: false },
      consentPolicyId: { type: DataTypes.UUID, allowNull: false },
      status: {
        type: DataTypes.ENUM("granted", "withdrawn", "expired", "superseded"),
        allowNull: false,
      },
      grantedAt: { type: DataTypes.DATE, allowNull: true },
      withdrawnAt: { type: DataTypes.DATE, allowNull: true },
      source: { type: DataTypes.STRING(32), allowNull: false },
      ipHash: { type: DataTypes.STRING(64), allowNull: true },
      userAgent: { type: DataTypes.STRING(512), allowNull: true },
      evidence: {
        type: DataTypes.JSON,
        allowNull: true,
        get() {
          return parseJsonColumn<Record<string, unknown>>(
            this.getDataValue("evidence")
          );
        },
      },
      createdAt: DataTypes.DATE,
      updatedAt: DataTypes.DATE,
    },
    {
      sequelize,
      modelName: "ParticipantConsentRecord",
      tableName: "ParticipantConsentRecords",
    }
  );
  return ParticipantConsentRecord;
}
