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

export class ParticipantProfile extends Model<
  InferAttributes<ParticipantProfile>,
  InferCreationAttributes<ParticipantProfile>
> {
  declare id: CreationOptional<string>;
  declare userId: string;
  declare status: CreationOptional<ParticipantProfileStatus>;
  declare onboardingIntent: CreationOptional<OnboardingIntent>;
  declare countryCode: CreationOptional<string | null>;
  declare regionCode: CreationOptional<string | null>;
  declare ageBand: CreationOptional<string | null>;
  declare profileAttributes: CreationOptional<Record<string, unknown> | null>;
  declare profileVersion: CreationOptional<number>;
  declare onboardingCompletedAt: CreationOptional<Date | null>;
  declare lastProfileReviewAt: CreationOptional<Date | null>;
  declare closedAt: CreationOptional<Date | null>;
  declare createdAt: CreationOptional<Date>;
  declare updatedAt: CreationOptional<Date>;
}

export function initParticipantProfileModel(sequelize: Sequelize) {
  ParticipantProfile.init(
    {
      id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        primaryKey: true,
      },
      userId: { type: DataTypes.UUID, allowNull: false, unique: true },
      status: {
        type: DataTypes.ENUM("incomplete", "active", "paused", "closed"),
        allowNull: false,
        defaultValue: "incomplete",
      },
      onboardingIntent: {
        type: DataTypes.ENUM("participate", "both"),
        allowNull: false,
        defaultValue: "participate",
      },
      countryCode: { type: DataTypes.STRING(2), allowNull: true },
      regionCode: { type: DataTypes.STRING(64), allowNull: true },
      ageBand: { type: DataTypes.STRING(16), allowNull: true },
      profileAttributes: {
        type: DataTypes.JSON,
        allowNull: true,
        get() {
          return parseJsonColumn<Record<string, unknown>>(
            this.getDataValue("profileAttributes")
          );
        },
      },
      profileVersion: {
        type: DataTypes.INTEGER,
        allowNull: false,
        defaultValue: 1,
      },
      onboardingCompletedAt: { type: DataTypes.DATE, allowNull: true },
      lastProfileReviewAt: { type: DataTypes.DATE, allowNull: true },
      closedAt: { type: DataTypes.DATE, allowNull: true },
      createdAt: DataTypes.DATE,
      updatedAt: DataTypes.DATE,
    },
    {
      sequelize,
      modelName: "ParticipantProfile",
      tableName: "ParticipantProfiles",
    }
  );
  return ParticipantProfile;
}
