import bcrypt from 'bcryptjs';
import mongoose, { Document, Schema } from 'mongoose';

export interface IUser extends Document {
  firstName: string;
  lastName: string;
  email: string;
  password: string;
  userType: 'doctor' | 'patient' | 'admin' | 'staff' | 'dentist';
  phone?: string;
  profileImage?: string;
  lastLogin?: Date;
  isActive: boolean;
  language: 'es' | 'en';
  isDentist?: boolean;
  resetPasswordToken?: string;
  resetPasswordExpire?: Date;
  ownerId?: mongoose.Types.ObjectId; // Reference to the primary account owner
  createdAt: Date;
  updatedAt: Date;
  clinic?: {
    name?: string;
    address?: string;
    phone?: string;
  };
  comparePassword(enteredPassword: string): Promise<boolean>;
  generatePasswordResetToken(): string;
}

const userSchema = new Schema<IUser>(
  {
    firstName: {
      type: String,
      required: [true, 'Please provide a first name'],
      trim: true,
    },
    lastName: {
      type: String,
      required: [true, 'Please provide a last name'],
      trim: true,
    },
    email: {
      type: String,
      required: [true, 'Please provide an email'],
      unique: true,
      lowercase: true,
      match: [
        /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
        'Please provide a valid email',
      ],
    },
    password: {
      type: String,
      required: false, // Password is generated after subscription
      minlength: 6,
      select: false,
    },
    userType: {
      type: String,
      enum: ['doctor', 'patient', 'admin', 'staff', 'dentist'],
      default: 'patient',
    },
    phone: {
      type: String,
    },
    profileImage: {
      type: String,
    },
    lastLogin: {
      type: Date,
    },
    isActive: {
      type: Boolean,
      default: true,
    },
    language: {
      type: String,
      enum: ['es', 'en'],
      default: 'es',
    },
    isDentist: {
      type: Boolean,
      default: false,
    },
    resetPasswordToken: {
      type: String,
      select: false,
    },
    resetPasswordExpire: {
      type: Date,
      select: false,
    },
    ownerId: {
      type: Schema.Types.ObjectId,
      ref: 'User',
    },
    clinic: {
      name: { type: String, trim: true },
      address: { type: String, trim: true },
      phone: { type: String, trim: true },
    },
  },
  { timestamps: true }
);

// Hash password before saving
userSchema.pre('save', async function (next) {
  if (!this.isModified('password')) {
    return next();
  }

  try {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
    next();
  } catch (error: any) {
    next(error);
  }
});

// Method to compare password
userSchema.methods.comparePassword = async function (
  enteredPassword: string
): Promise<boolean> {
  return await bcrypt.compare(enteredPassword, this.password);
};

// Generate password reset token
userSchema.methods.generatePasswordResetToken = function (): string {
  const resetToken = Math.random().toString(36).slice(-8);
  this.resetPasswordToken = resetToken;
  this.resetPasswordExpire = new Date(Date.now() + 1 * 60 * 60 * 1000); // 1 hour
  return resetToken;
};

export default mongoose.model<IUser>('User', userSchema);
