const validator = require("validator");
const db = require("../../../managers/dbConfig");
const { generateID } = require("../../../managers/idGenerator");
const { getAgeFromDOB } = require("../../../managers/customFormaters");
const e = require("cors");

// //let counter = 0;

// const patientReg = async (req, res) => {
//  // pageUser = req.user.cadre;

// //   if (pageUser !== "Medical Record Officer" && pageUser !== "MRO")
// //     throw "Intuder Detected!!!\n Operation Aborted!";

//   let {
//     title,
//     firstName,
//     lastName,
//     address,
//     phoneNumber,
//     email,
//     gender,
//     age,
//     religion,
//     hmo,
//   } = req.body;

//   if (!firstName) throw "First Name can't be empty";
//   if (!lastName) throw "Last Name can't be empty";
//   if (!address) throw "address can't be empty";
//  // if (!phoneNumber) throw "Phone Number can't be empty";

//   if (!gender) throw "Gender can't be empty";
//   if (!age) throw "Age can't be empty";

//   title = title ?? null;
//   phoneNumber = !phoneNumber ? null : phoneNumber;
//   email = !email ? null : email;
//   hmo = hmo ?? null;
//   religion = religion ?? null;
//   if (phoneNumber != null ){
//       if(phoneNumber.length < 11) throw "Phone Number NOT completed";
//   }
//   // dateReg = new Date()
//   //   .toISOString()
//   //   .replace(/T|\.+.*/g, (match) => (match === "T" ? " " : ""));

//   let pt_id = "N/A";
//   let nok_id = 0;
//   let nok_num = "N/A";

//   const sql = `INSERT INTO patients (
//     title,
//     firstName,
//     lastName,
//     Address,
//     phone_num,
//     email,
//     gender,
//     Age,
//     religion,
//     HMO,
//     patient_id,
//     nok_id,
//     nok_num
//     ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)`;

//   const sql1 = `UPDATE patients SET patient_id=? WHERE id = ?`;
//   const sql2 = `SELECT id,title,firstName, lastName, patient_id, phone_num, date_time FROM patients WHERE firstName = ? AND lastName=? AND Address=?`;
//   const sql3 = `SELECT COUNT(*) FROM patients WHERE phone_num = ? OR email=?`;

//   const connection = await db.getConnection();
//     await connection.beginTransaction(); // Start transaction

//   const [phoneAndEmailCount] = await connection.execute(sql3, [phoneNumber, email]);
//   //console.log(phoneAndEmailCount[0]);
//   const ptExist = phoneAndEmailCount[0]["COUNT(*)"] > 0;

//   if (ptExist)
//     throw `A Patient with the Phone Number: ${phoneNumber} OR Email: ${email} already exist`;

//   await connection.execute(sql, [
//     title,
//     firstName,
//     lastName,
//     address,
//     phoneNumber,
//     email,
//     gender,
//     age,
//     religion,
//     hmo,
//     pt_id,
//     nok_id,
//     nok_num,
//   ]);

//   const [getPT] = await connection.execute(sql2, [firstName, lastName, address]);
//   // console.log(getPT[0]);

//   const patient_id = await generateID(getPT[0], req.user.branch_id);

//   await connection.execute(sql1, [patient_id, getPT[0].id]);

//   const [upDated] = await connection.execute(sql2, [firstName, lastName, address]);
//   delete upDated[0].id;
//   await connection.commit(); // Commit transaction
//     connection.release();

//   res.status(201).json({
//     status: " Success",
//     message: "New Patient Registered Successfully",
//     ...upDated[0],
//   });
// };

// // REGISTER patient's next of kin

// const nok = async (req, res) => {
//   const pageUser = req.user.cadre;
// //   if (pageUser !== "Medical Record Officer" && pageUser !== "MRO")
// //     throw "You're not authorized to perform this task";
//   try {
//     let {
//       title,
//       fName,
//       lName,
//       nok_phoneNumber,
//       houseNum_or_name,
//       str,
//       city_and_state,
//       country,
//       email,
//       patient_id,
//       relationship,
//     } = req.body;

//     title = title ?? null;
//     email = email ?? null;
//     houseNum_or_name = houseNum_or_name ?? "N/A";
//     str = str ?? "N/A";
//     city_and_state = city_and_state ?? "N/A";
//     country = country ?? "N/A";

//     if (!nok_phoneNumber) throw "Next Of Kin Phone Number Is Mandatory";

//     const sql = `INSERT INTO next_of_kin (title,firstName, lastName,phone_num,houseNum_or_name,street,city_and_state,country,email,patient_id,relationship) VALUES (?,?,?,?,?,?,?,?,?,?,?)`;
//     const sql1 = `SELECT id,title,firstName,lastName,phone_num,patient_id,relationship FROM next_of_kin WHERE patient_id = ?`;
//     const sql2 = `UPDATE patients SET nok_id=?, nok_num=? WHERE patient_id=?`;
//     const sql3 = `SELECT COUNT(*) FROM next_of_kin WHERE patient_id = ?`;
//     const sql4 = `SELECT COUNT(patient_id) FROM patients WHERE patient_id = ?`;

//     const connection = await db.getConnection();
//     await connection.beginTransaction();

//     const [ptIdRows] = await connection.execute(sql4, [patient_id]);
//     if (ptIdRows[0]["COUNT(patient_id)"] === 0)
//       throw `INCORRECT Patient-ID: ${patient_id}`;

//     const [rows] = await connection.execute(sql3, [patient_id]);
//     if (rows[0]["COUNT(*)"] > 0)
//       throw `Next of Kin record already exist for patient with ID: ${patient_id}`;

//     await connection.execute(sql, [
//       title,
//       fName,
//       lName,
//       nok_phoneNumber,
//       houseNum_or_name,
//       str,
//       city_and_state,
//       country,
//       email,
//       patient_id,
//       relationship,
//     ]);

//     const [NOK] = await connection.execute(sql1, [patient_id]);
//     await connection.execute(sql2, [NOK[0].id, nok_phoneNumber, patient_id]);
//     delete [NOK][0].id;

//      await connection.commit(); // Commit transaction
//     connection.release();

//     res.status(201).json({
//       status: "success",
//       message: "Next of Kin record saved successfully",
//       data: NOK[0],
//     });
//   } catch (e) {
//     res.status(400).json({
//       status: "failed",
//       error: e,
//     });
//   }
// };

// module.exports = { patientReg, nok };

const registerPatientWithNok = async (req, res, next) => {
  let connection;
  try {
    const {
      title,
      firstName,
      lastName,
      phoneNumber,
      email,
      gender,
      date_of_birth,
      religion,
      hmo,
      groupORfamily,
      houseNumOrName,
      street,
      state,
      country,
      nok_title,
      nok_firstName,
      nok_lastName,
      nok_phoneNumber,
      nok_houseNum_or_name,
      nok_street,
      nok_city_and_state,
      nok_country,
      nok_email,
      nok_relationship,
    } = req.body;

    const checkPatientExistenceQuery = `SELECT COUNT(*) FROM patients WHERE phone_num = ? OR email = ?`;
    const getPatientIdQuery = `SELECT id, title, firstName, lastName, patient_id, phone_num, date_time FROM patients WHERE firstName = ? AND lastName = ? AND Address = ?`;
    const insertPatientQuery = `INSERT INTO patients (title, firstName, lastName, Address, phone_num, houseNum_or_name, street, city_and_state, country, email, gender,age, religion, hmo, family_or_group, patient_id, nok_id, nok_num, date_of_birth) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?)`;
    const updatePatientIdQuery = `UPDATE patients SET patient_id = ? WHERE id = ?`;
    const insertNokQuery = `INSERT INTO next_of_kin (title, firstName, lastName, phone_num, houseNum_or_name, street, city_and_state, country, email, patient_id, relationship) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;

    const getNokDataQuery = `SELECT id, title, firstName, lastName, phone_num, patient_id, relationship FROM next_of_kin WHERE patient_id = ?`;
    const updatePatientNokQuery = `UPDATE patients SET nok_id = ?, nok_num = ? WHERE patient_id = ?`;

    // Patient Validation
    if (!firstName)
      throw "Patient First Name can NOT be empty for registration";
    if (!lastName) throw "Patient Last Name can NOT be empty for registration";
    // if (!address) throw "Patient address can NOT be empty for registration";
    if (!gender) throw "Patient's Gender can NOT be empty for registration";
    if (!date_of_birth)
      throw "Patient's date_of_birth can NOT be empty for registration";
    // if (!validator.isNumeric(age.toString()))
    //   throw `${age} is not a valid amount`;

    const patientTitle = title ?? null;
    const patientPhoneNumber = !phoneNumber ? null : phoneNumber;
    const patientEmail = !email ? null : email;
    const patientHmo = hmo ?? null;
    const familyOrGroup = groupORfamily ?? null;
    const patientReligion = religion ?? null;
    const age = getAgeFromDOB(date_of_birth);

    if (patientPhoneNumber && patientPhoneNumber.length < 11) {
      throw "Phone Number NOT completed";
    }

    // Next of Kin Validation nok_firstName
    if (!nok_phoneNumber) throw "Next Of Kin Phone Number Is Mandatory";
    //if (!nok_firstName) throw "Next Of Kin first Name Is Mandatory";

    const nokTitle = nok_title ?? null;
    const nokEmail = nok_email ?? null;
    const nokHouseNumOrName = nok_houseNum_or_name ?? "N/A";
    const nokStreet = nok_street ?? "N/A";
    const nokCityAndState = nok_city_and_state ?? "N/A";
    const nokCountry = nok_country ?? "N/A";
    const address =
      houseNumOrName + "," + " " + street + "," + " " + state + " " + country;

    connection = await db.getConnection();
    await connection.beginTransaction();

    // Check if patient with phone or email already exists

    const [patientExistenceResult] = await connection.execute(
      checkPatientExistenceQuery,
      [patientPhoneNumber, patientEmail]
    );

    if (patientExistenceResult[0]["COUNT(*)"] > 0) {
      throw `A Patient with the Phone Number: ${patientPhoneNumber} OR Email: ${patientEmail} already exists`;
    }

    // Insert Patient Data

    await connection.execute(insertPatientQuery, [
      patientTitle,
      firstName,
      lastName,
      address,
      patientPhoneNumber,
      houseNumOrName,
      street,
      state,
      country,
      patientEmail,
      gender,
      age,
      patientReligion,
      patientHmo,
      familyOrGroup,
      "N/A", // patient_id, will be updated later
      0, // nok_id, will be updated later
      "N/A", // nok_num, will be updated later
      date_of_birth, // date_of_birth
    ]);

    // Retrieve the patient's ID after insertion

    const [patientData] = await connection.execute(getPatientIdQuery, [
      firstName,
      lastName,
      address,
    ]);

    const patient_id = await generateID(patientData[0], req.user.branch_id);

    // Update the patient's record with the generated patient_id

    await connection.execute(updatePatientIdQuery, [
      patient_id,
      patientData[0].id,
    ]);

    // Insert Next of Kin Data

    await connection.execute(insertNokQuery, [
      nokTitle,
      nok_firstName,
      nok_lastName,
      nok_phoneNumber,
      nokHouseNumOrName,
      nokStreet,
      nokCityAndState,
      nokCountry,
      nokEmail,
      patient_id,
      nok_relationship,
    ]);

    // Retrieve the Next of Kin's ID
    const [nokData] = await connection.execute(getNokDataQuery, [patient_id]);

    // Update the patient's record with the Next of Kin's ID and phone number

    await connection.execute(updatePatientNokQuery, [
      nokData[0].id,
      nok_phoneNumber,
      patient_id,
    ]);

    delete patientData[0].id;
    delete nokData[0].id;

    await connection.commit();
    connection.release();

    res.status(201).json({
      status: "success",
      message: "Patient and Next of Kin registered successfully",
      patient: patientData[0],
      nok: nokData[0],
    });
  } catch (error) {
    // console.log(error);
    if (connection) {
      await connection.rollback();
      connection.release();
    }
    res.status(400).json({ status: "failed", error: error });
  }
};

const updatePatientWithNok = async (req, res) => {
  let connection;
  try {
    const { patientId } = req.query;

    if (!patientId) throw "Patient ID is required for updating.";

    const {
      title,
      firstName,
      lastName,
      address,
      phoneNumber,
      email,
      gender,
      age,
      religion,
      hmo,
      groupORfamily,
      date_of_birth,
      nok_title,
      nok_firstName,
      nok_lastName,
      nok_phoneNumber,
      nok_houseNum_or_name,
      nok_street,
      nok_city_and_state,
      nok_country,
      nok_email,
      nok_relationship,
    } = req.body;

    connection = await db.getConnection();
    await connection.beginTransaction();

    // Update Patient Data
    let updatePatientQuery = `UPDATE patients SET `;
    const patientUpdates = [];
    const patientValues = [];

    if (title !== undefined && title !== "") {
      patientUpdates.push(`title = ?`);
      patientValues.push(title);
    }
    if (firstName !== undefined && firstName !== "") {
      patientUpdates.push(`firstName = ?`);
      patientValues.push(firstName);
    }
    if (lastName !== undefined && lastName !== "") {
      patientUpdates.push(`lastName = ?`);
      patientValues.push(lastName);
    }
    if (address !== undefined && address !== "") {
      patientUpdates.push(`Address = ?`);
      patientValues.push(address);
    }
    if (phoneNumber !== undefined && phoneNumber !== "") {
      patientUpdates.push(`phone_num = ?`);
      patientValues.push(phoneNumber);
    }
    if (email !== undefined && email !== "") {
      patientUpdates.push(`email = ?`);
      patientValues.push(email);
    }
    if (gender !== undefined && gender !== "") {
      patientUpdates.push(`gender = ?`);
      patientValues.push(gender);
    }
    if (age !== undefined && age !== "") {
      patientUpdates.push(`Age = ?`);
      patientValues.push(parseInt(age)); // Assuming age should be a number
    }
    if (religion !== undefined && religion !== "") {
      patientUpdates.push(`religion = ?`);
      patientValues.push(religion);
    }
    if (hmo !== undefined && hmo !== "") {
      patientUpdates.push(`HMO = ?`);
      patientValues.push(hmo);
    }
    // family_or_group
    if (groupORfamily !== undefined && groupORfamily !== "") {
      patientUpdates.push(`family_or_group = ?`);
      patientValues.push(groupORfamily);
    }

    if (date_of_birth !== undefined && date_of_birth !== "") {
      patientUpdates.push(`date_of_birth = ?`);
      patientValues.push(date_of_birth);
    }

    if (patientUpdates.length > 0) {
      updatePatientQuery += patientUpdates.join(", ");
      updatePatientQuery += ` WHERE patient_id = ?`;
      patientValues.push(patientId);
      await connection.execute(updatePatientQuery, patientValues);
    } else {
      // If no patient data is provided, throw an error
      throw "No patient data provided for update.";
    }

    // Update Next of Kin Data
    const checkNokExistenceQuery = `SELECT nok_id FROM patients WHERE patient_id = ?`;
    const [nokExistenceResult] = await connection.execute(
      checkNokExistenceQuery,
      [patientId]
    );

    const nokId = nokExistenceResult[0]?.nok_id;

    if (nokId) {
      let updateNokQuery = `UPDATE next_of_kin SET `;
      const nokUpdates = [];
      const nokValues = [];

      if (nok_title !== undefined && nok_title !== "") {
        nokUpdates.push(`title = ?`);
        nokValues.push(nok_title);
      }
      if (nok_firstName !== undefined && nok_firstName !== "") {
        nokUpdates.push(`firstName = ?`);
        nokValues.push(nok_firstName);
      }
      if (nok_lastName !== undefined && nok_lastName !== "") {
        nokUpdates.push(`lastName = ?`);
        nokValues.push(nok_lastName);
      }
      if (nok_phoneNumber !== undefined && nok_phoneNumber !== "") {
        nokUpdates.push(`phone_num = ?`);
        nokValues.push(nok_phoneNumber);
        // If NOK phone number is updated, also update it in the patients table
        const updatePatientNokNumQuery = `UPDATE patients SET nok_num = ? WHERE patient_id = ?`;
        await connection.execute(updatePatientNokNumQuery, [
          nok_phoneNumber,
          patientId,
        ]);
      }
      if (nok_houseNum_or_name !== undefined && nok_houseNum_or_name !== "") {
        nokUpdates.push(`houseNum_or_name = ?`);
        nokValues.push(nok_houseNum_or_name);
      }
      if (nok_street !== undefined && nok_street !== "") {
        nokUpdates.push(`street = ?`);
        nokValues.push(nok_street);
      }
      if (nok_city_and_state !== undefined && nok_city_and_state !== "") {
        nokUpdates.push(`city_and_state = ?`);
        nokValues.push(nok_city_and_state);
      }
      if (nok_country !== undefined && nok_country !== "") {
        nokUpdates.push(`country = ?`);
        nokValues.push(nok_country);
      }
      if (nok_email !== undefined && nok_email !== "") {
        nokUpdates.push(`email = ?`);
        nokValues.push(nok_email);
      }
      if (nok_relationship !== undefined && nok_relationship !== "") {
        nokUpdates.push(`relationship = ?`);
        nokValues.push(nok_relationship);
      }

      if (nokUpdates.length > 0) {
        updateNokQuery += nokUpdates.join(", ");
        updateNokQuery += ` WHERE id = ?`;
        nokValues.push(nokId);
        await connection.execute(updateNokQuery, nokValues);
      }
    } else if (
      (nok_firstName !== undefined && nok_firstName !== "") ||
      (nok_lastName !== undefined && nok_lastName !== "") ||
      (nok_phoneNumber !== undefined && nok_phoneNumber !== "") ||
      (nok_relationship !== undefined && nok_relationship !== "")
      // Add other mandatory NOK fields checks if needed for initial creation
    ) {
      // If NOK doesn't exist but NOK data is provided (and not empty), create a new NOK record
      const insertNokQuery = `INSERT INTO next_of_kin (title, firstName, lastName, phone_num, houseNum_or_name, street, city_and_state, country, email, patient_id, relationship) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
      const [newNokResult] = await connection.execute(insertNokQuery, [
        nok_title !== undefined && nok_title !== "" ? nok_title : null,
        nok_firstName !== undefined && nok_firstName !== ""
          ? nok_firstName
          : null,
        nok_lastName !== undefined && nok_lastName !== "" ? nok_lastName : null,
        nok_phoneNumber !== undefined && nok_phoneNumber !== ""
          ? nok_phoneNumber
          : null,
        nok_houseNum_or_name !== undefined && nok_houseNum_or_name !== ""
          ? nok_houseNum_or_name
          : "N/A",
        nok_street !== undefined && nok_street !== "" ? nok_street : "N/A",
        nok_city_and_state !== undefined && nok_city_and_state !== ""
          ? nok_city_and_state
          : "N/A",
        nok_country !== undefined && nok_country !== "" ? nok_country : "N/A",
        nok_email !== undefined && nok_email !== "" ? nok_email : null,
        patientId,
        nok_relationship !== undefined && nok_relationship !== ""
          ? nok_relationship
          : null,
      ]);

      if (
        newNokResult.insertId &&
        nok_phoneNumber !== undefined &&
        nok_phoneNumber !== ""
      ) {
        const newNokId = newNokResult.insertId;
        const updatePatientNokIdQuery = `UPDATE patients SET nok_id = ?, nok_num = ? WHERE patient_id = ?`;
        await connection.execute(updatePatientNokIdQuery, [
          newNokId,
          nok_phoneNumber,
          patientId,
        ]);
      }
    }

    await connection.commit();
    connection.release();

    // Fetch updated patient and NOK data for response
    const getUpdatedPatientQuery = `SELECT * FROM patients WHERE patient_id = ?`;
    const [updatedPatientData] = await connection.execute(
      getUpdatedPatientQuery,
      [patientId]
    );

    let updatedNokData = null;
    if (updatedPatientData[0]?.nok_id) {
      const getUpdatedNokQuery = `SELECT * FROM next_of_kin WHERE id = ?`;
      const [nokResult] = await connection.execute(getUpdatedNokQuery, [
        updatedPatientData[0].nok_id,
      ]);
      updatedNokData = nokResult[0];
    }

    res.status(200).json({
      status: "success",
      message: "Patient and Next of Kin updated successfully",
      patient: updatedPatientData[0],
      nok: updatedNokData,
    });
  } catch (error) {
    if (connection) {
      await connection.rollback();
      connection.release();
    }
    // console.error("Error updating patient:", error);
    res.status(400).json({ status: "failed", error: error });
  }
};

module.exports = { registerPatientWithNok, updatePatientWithNok };
