import { Request, Response } from "express";
import User from "../models/user";
import bcrypt from "bcrypt";
import { LoginProvider, UserRole, UserStatus } from "../types/types";
import { stripe } from "../utils/stripeInstance";
import notificationSetrtings from "../models/notificationSettings";
import NotificationSettings from "../models/notificationSettings";
import { isValidEmail, parseOptionalDate } from "../utils/helperFunctions";
import { sendEmail } from "../utils/mailer";

class SignupController {
  static async Execute(req: Request, res: Response) {
    const PASSWORD_REGEX =
      /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>]).{8,20}$/;
    const saltRounds = 10;

    const { name, email, password, loginProvider, role } = req.body;
    const birthday = parseOptionalDate(req.body.birthday);
    const anniversary = parseOptionalDate(req.body.anniversary);

    if (
      typeof email !== "string" ||
      typeof password !== "string" ||
      !name ||
      !email ||
      !password ||
      !loginProvider ||
      !role
    ) {
      return res.status(400).send({
        message: "Invalid request",
      });
    }

    if (!isValidEmail(email)) {
      return res.status(400).send({
        message: "Invalid email provided.",
      });
    }

    if (!birthday.valid) {
      return res.status(400).send({
        message: "Invalid birthday provided.",
      });
    }

    if (!anniversary.valid) {
      return res.status(400).send({
        message: "Invalid anniversary provided.",
      });
    }

    // Check if role is a valid UserRole
    if (!Object.values(UserRole).includes(role)) {
      return res.status(400).send({
        message: "Invalid role provided.",
      });
    }

    // Check if loginProvider is a valid loginProvider
    if (!Object.values(LoginProvider).includes(loginProvider)) {
      return res.status(400).send({
        message: "Invalid loginProvider provided.",
      });
    }

    // Validate the password against the regex
    if (!PASSWORD_REGEX.test(password)) {
      return res.status(400).send({
        message:
          "Password must be 8-20 characters long, with at least one uppercase, one lowercase, one digit, and one special character.",
      });
    }

    const user = await User.findOne({ email: email });
    if (user) {
      return res.status(400).send({
        message: "User already exists",
      });
    }

    try {
      bcrypt.hash(password, saltRounds).then(async function (hash: string) {
        const customer = await stripe.customers.create({
          name: name.trim(),
          email: email.trim().toLowerCase(),
        });

        const newUser = await User.create({
          name: name.trim(),
          email: email.trim().toLowerCase(),
          password: hash,
          loginProvider: loginProvider,
          role: role,
          stripeCustomerId: customer.id,
          birthday: birthday.date,
          anniversary: anniversary.date,
          status: role === "Vendor" ? UserStatus.pending : UserStatus.active,
        });

        const notificationSettings = new NotificationSettings({
          user: newUser._id, // Link to the user
        });
        await notificationSettings.save().catch((err: any) => console.log(err));

        if (role === UserRole.vendor) {
          sendEmail({
            to: newUser.email,
            subject: "Welcome to Before The Dates - Account Pending Approval",
            template: "vendorSignupPending",
            variables: {
              vendorName: newUser.name,
              platformName: "Before The Dates",
            },
          })
            .then(() => console.log("✅ Email sent"))
            .catch((err) => console.error("❌ Error sending email", err));
        }

        const userWithoutPassword = newUser.toJSON(); // Converts Sequelize model instance to plain object
        delete userWithoutPassword.password;

        res.status(200).send({
          message: "User created successfully",
          user: userWithoutPassword,
        });

        return;
      });
    } catch (error) {
      console.log(error);
      res.status(500).send({
        message: "Error creating user",
      });
    }
  }
}

module.exports = SignupController;
