const dayjs = require("dayjs");
const utc = require("dayjs/plugin/utc");

dayjs.extend(utc);

/**
 * Calculates age from a date string.
 * Returns:
 * - "X years" if >= 1 year
 * - "X months Y days" if < 1 year
 * - "X days" if < 1 month (less than 29 days)
 */
function getAgeFromDOB(dob) {
  const birthDate = dayjs.utc(dob).startOf("day");
  const today = dayjs.utc().startOf("day");

  const years = today.diff(birthDate, "year");
  if (years >= 1) return `${years} year${years > 1 ? "s" : ""}`;

  const months = today.diff(birthDate, "month");
  const temp = birthDate.add(months, "month");
  const days = today.diff(temp, "day");

  if (months === 0 && days < 29) {
    return `${days} day${days > 1 ? "s" : ""}`;
  }

  return `${months} month${months > 1 ? "s" : ""} ${days} day${
    days !== 1 ? "s" : ""
  }`;
}

// Attaches calculated ages to patient records
// and formats date_of_birth to "YYYY-MM-DD" if it exists.
function attachCalculatedAges(patients) {
  return patients.map((patient) => {
    const dob = patient.date_of_birth;
    return {
      ...patient,
      age: dob ? getAgeFromDOB(dob) : patient.age,
      date_of_birth: dob ? dayjs.utc(dob).format("YYYY-MM-DD") : null,
    };
  });
}

const cleanVitalsData = (data) => {
  // If data is null or undefined, return it as is
  if (!data) return data;

  // Convert single object into an array for processing
  const dataArray = Array.isArray(data) ? data : [data];

  const cleanedData = dataArray.map((item) => ({
    ...item,
    temp: item.temp == "0.0" ? "--" : item.temp,
    weight: item.Weight == 0 ? "--" : item.Weight,
    height: item.height == 0 ? "--" : item.height,
    systolic: item.systolic == 0 ? "--" : item.systolic,
    diastolic: item.diastolic == 0 ? "--" : item.diastolic,
    pulse_rate: item.pulse_rate == 0 ? "--" : item.pulse_rate,
    resp_rate: item.resp_rate == 0 ? "--" : item.resp_rate,
  }));

  // Return single object if the input was not an array
  return Array.isArray(data) ? cleanedData : cleanedData[0];
};

function formatCurrency(amountString) {
  // 1. Split the string into integer and fractional parts (if any)
  const [integerPart, fractionalPart] = amountString.split(".");

  // 2. Format the integer part with commas
  const formattedIntegerPart = integerPart.replace(
    /\B(?=(\d{3})+(?!\d))/g,
    ","
  );

  // 3. Recombine the formatted parts
  if (fractionalPart) {
    return `${formattedIntegerPart}.${fractionalPart}`;
  } else {
    return formattedIntegerPart;
  }
}

function formatCurrency(amountString) {
  const [integerPart, fractionalPart] = amountString.split(".");
  const formattedIntegerPart = integerPart.replace(
    /\B(?=(\d{3})+(?!\d))/g,
    ","
  );
  return fractionalPart
    ? `${formattedIntegerPart}.${fractionalPart}`
    : formattedIntegerPart;
}

function formatCurrencyForObjects(dataArray) {
  if (!Array.isArray(dataArray)) {
    console.error("Input must be an array of objects.");
    return [];
  }

  return dataArray.map((item) => {
    // Create a copy to avoid modifying the original object directly
    const newItem = { ...item };

    switch (true) {
      case newItem.total_bill !== undefined:
        if (newItem.total_bill == undefined || newItem.total_bill == null)
          break;
        // Check if total_bill is a string and contains a number
        // if (typeof newItem.total_bill === "string") {
        //   const numberValue = parseFloat(newItem.total_bill.replace(/,/g, ""));
        //   if (!isNaN(numberValue)) {
        //     newItem.total_bill = numberValue; // Convert to number
        //   } else {
        //     newItem.total_bill = 0; // Set to 0 or handle as needed
        //   }
        // }
        newItem.total_bill = formatCurrency(newItem.total_bill);
      case newItem.net_payable !== undefined:
        if (newItem.net_payable == undefined || newItem.net_payable == null)
          break;
        newItem.net_payable = formatCurrency(newItem.net_payable);
      case newItem.discount_amount !== undefined:
        if (
          newItem.discount_amount == undefined ||
          newItem.discount_amount == null
        )
          break;
        newItem.discount_amount = formatCurrency(newItem.discount_amount);
      case newItem.vat_amount !== undefined:
        if (newItem.vat_amount == undefined || newItem.vat_amount == null)
          break;
        newItem.vat_amount = formatCurrency(newItem.vat_amount);
        break;
      // Add more cases here for other currency fields as needed
      // case newItem.some_other_currency_field !== undefined:
      //   newItem.some_other_currency_field = formatCurrency(newItem.some_other_currency_field);
      //   break;
      // case newItem.yet_another_currency_field !== undefined:
      //    newItem.yet_another_currency_field = formatCurrency(newItem.yet_another_currency_field);
      //    break;
      default:
        // No currency field to format in this object
        break;
    }
    return newItem;
  });
}

// another approach handling potential errors:
function formatCurrency2(amountString) {
  try {
    const num = Number(amountString); // Try converting to a number first
    if (isNaN(num)) {
      return "Invalid input"; // Or handle the error as needed
    }
    const [integerPart, fractionalPart] = String(num).split("."); // Use the number to split.

    const formattedIntegerPart = integerPart.replace(
      /\B(?=(\d{3})+(?!\d))/g,
      ","
    );
    return fractionalPart
      ? `${formattedIntegerPart}.${fractionalPart}`
      : formattedIntegerPart;
  } catch (error) {
    return "Error formatting currency"; // Or throw the error if you prefer
  }
}

module.exports = {
  cleanVitalsData,
  formatCurrency,
  formatCurrency2,
  formatCurrencyForObjects,
  getAgeFromDOB,
  attachCalculatedAges,
};
