import { rollbackTransaction } from "@/database/configuration/connection";
import {
  ConvertQueryResultToJSON,
  ServerAction,
  ServerResponse,
} from "@/lib/actions";
import { encrypt } from "@/lib/encryption";
import { generatePassword } from "@/lib/password";
import compilers from "@/models/email";
import { ResultSetHeader, RowDataPacket } from "mysql2";
import { v4 } from "uuid";
import { sendMail } from "../nodemailer";

export default async function createUser(formData: FormData) {
  const { con, dict } = await ServerAction();

  if ("error" in con) {
    return ServerResponse({
      operation: false,
      message: dict.alerts.general.connection_fail,
    });
  }

  const name = formData.get("name");
  const email = formData.get("email");
  const permission = formData.get("permission");

  try {
    const id = v4();
    const password = generatePassword(8);
    const encrypted = await encrypt(password);

    await con.beginTransaction();

    const [users] = await con.query<RowDataPacket[]>(
      "SELECT * FROM USERS WHERE (NAME != NULL AND NAME = ?) OR EMAIL = ?",
      [name, email],
    );

    if (users.length > 0) {
      return ServerResponse({
        operation: false,
        message: dict.alerts.create_profile.error_not_available,
      });
    }

    await con.query<ResultSetHeader>(
      `
        INSERT INTO USERS (
          ID,
          NAME,
          EMAIL,
          PASSWORD,
          PERMISSIONS
        ) VALUES (?, ?, ?, ?, ?)
      `,
      [id, name, email, encrypted, permission],
    );

    const [user] = await con.query<RowDataPacket[]>(
      "SELECT * FROM USERS WHERE ID = ?",
      [id],
    );

    await con.commit();

    await sendMail({
      subject: "New Account",
      toEmail: email as string,
      optText: compilers.new_user({ email, password }),
    });

    return ServerResponse({
      operation: true,
      message: dict.alerts.create_profile.success,
      data: ConvertQueryResultToJSON(user)[0],
    });
  } catch (error) {
    rollbackTransaction(con);
    return ServerResponse({
      operation: false,
      message: dict.alerts.general.unexpected_error,
      data: error,
    });
  } finally {
    con.release();
  }
}
