import { DataTypes, Model, Optional } from "sequelize";
import Joi from "joi";
import sequelize from "../middlewears/sequelize";
import jwt from "jsonwebtoken";

export interface User {
  id: number;
  name: string;
  email: string;
  phoneNumber: string;
  password: string;
  role: "Admin" | "Shopkeeper" | "Tailor" | "Master";
  modules: string[]; // JSON array of module names
  isDeleted: boolean;
  createdAt?: Date;
  updatedAt?: Date;
}

interface UserOptionalAttribute extends Optional<User, "id"> {}

class UserModel extends Model<User, UserOptionalAttribute> implements User {
  public id!: number;
  public name!: string;
  public email!: string;
  public phoneNumber!: string;
  public password!: string;
  public role!: "Admin" | "Shopkeeper" | "Tailor" | "Master";
  public modules!: string[];
  public isDeleted!: boolean;

  // Timestamps
  public readonly createdAt!: Date;
  public readonly updatedAt!: Date;
}

// Initialize the model
UserModel.init(
  {
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    name: {
      type: DataTypes.STRING(100),
      allowNull: false,
    },
    email: {
      type: DataTypes.STRING(100),
      allowNull: false,
      unique: true,
      validate: {
        isEmail: true,
      },
    },
    phoneNumber: {
      type: DataTypes.STRING(20),
      allowNull: false,
      defaultValue: "",
    },
    password: {
      type: DataTypes.STRING(255),
      allowNull: false,
    },
    role: {
      type: DataTypes.ENUM("Admin", "Shopkeeper", "Tailor", "Master"),
      allowNull: false,
      defaultValue: "Admin",
    },
    modules: {
      type: DataTypes.JSON,
      allowNull: false,
      defaultValue: [],
    },
    isDeleted: {
      type: DataTypes.BOOLEAN,
      allowNull: false,
      defaultValue: false,
    },
    createdAt: {
      type: DataTypes.DATE,
      defaultValue: DataTypes.NOW,
    },
    updatedAt: {
      type: DataTypes.DATE,
      defaultValue: DataTypes.NOW,
    },
  },
  {
    tableName: "users",
    sequelize,
  }
);

// Joi validation schema for incoming requests
const userSchema = Joi.object({
  name: Joi.string().min(3).max(30).required(),
  email: Joi.string().email().required(),
  phoneNumber: Joi.string().max(20).optional().allow(""),
  password: Joi.string().min(6).required(),
  role: Joi.string()
    .valid("Admin", "Shopkeeper", "Tailor", "Master")
    .optional()
    .default("Admin"),
  modules: Joi.array().items(Joi.string()).optional().default([]),
});

// Joi validation schema for update requests (password and email are optional)
const updateUserSchema = Joi.object({
  name: Joi.string().min(3).max(30).optional(),
  email: Joi.string().email().optional(),
  phoneNumber: Joi.string().max(20).optional().allow(""),
  password: Joi.string().min(6).optional(),
  role: Joi.string()
    .valid("Admin", "Shopkeeper", "Tailor", "Master")
    .optional(),
  modules: Joi.array().items(Joi.string()).optional(),
});

// Generate JWT Token
const generateAuthToken = (user: User): string => {
  const payload = {
    id: user.id,
    email: user.email,
    role: user.role,
    createdAt: Date.now(),
  };

  const secret = "TheUniformCenter!@#$%54321";

  return jwt.sign(payload, secret, { algorithm: "HS256" });
};

export { UserModel, userSchema, updateUserSchema, generateAuthToken };
