import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { showToast } from "@/lib/toast";
import type { TypeAttributes } from "@/components/ui/types/common";
import { format, parseISO } from "date-fns";

import {
  convertUTCToISTForDisplay,
  formatDateDisplay,
} from "./utils/dateUtils";

export const PASSWORD_REGEX =
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d]).{8,}$/;

export const PASSWORD_REGEX_MESSAGE =
  "Password must include uppercase, lowercase, number, and special character.";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

export const isEmpty = (data: any, ignoreZero = false): boolean => {
  if (data == null) {
    return true;
  }

  if (typeof data === "string") {
    return ["", null, "null", undefined].includes(data);
  }

  if (Array.isArray(data)) {
    return data.length === 0;
  }

  if (typeof data === "object") {
    return Object.keys(data).length === 0;
  }

  if (typeof data === "number" && ignoreZero) {
    return data === 0;
  }
  return data.length === 0;
};

export const customizeToast = (
  title: string,
  type: TypeAttributes.Status = "success",
) => {
  return showToast(title, type);
};

export const formatDate = (dateString: string) => {
  return formatDateDisplay(dateString);
};

export const handleToastError = (response: any) => {
  if (response?.data?.error) {
    const status = response?.data?.status ?? 0;

    const code = response?.data?.code ?? null;

    if (code && [1001, 1002, 1003, 422, 500, 401].includes(code)) {
      !isEmpty(response?.data?.message) &&
        customizeToast(response?.data?.message, "danger");
    }

    if (status === 400) {
      customizeToast("Bad request", "danger");
    }

    if (status === 422) {
      const error = response?.data?.errors ?? [];
      const message = error.length > 0 ? error[0]?.message : "";
      !isEmpty(message) && customizeToast(message, "danger");
    }
  }

  // handle 404
  if (response?.status === 404) {
    customizeToast("Not found", "danger");
  }

  if (response?.data?.statusCode === 500) {
    customizeToast("Internal server error", "danger");
  }
};

export const CustomizeFormatDate = (dateString: string) => {
  return formatDateDisplay(dateString);
};

export const convertToLocalTime = (dateString: string) => {
  return convertUTCToISTForDisplay(dateString);
};

export const getAvatarColor = (name: string) => {
  const colors = [
    "bg-blue-400 text-blue-900",
    "bg-amber-400 text-amber-900",
    "bg-pink-300 text-pink-900",
    "bg-purple-400 text-purple-900",
    "bg-green-400 text-green-900",
    "bg-red-400 text-red-900",
    "bg-cyan-400 text-cyan-900",
    "bg-orange-400 text-orange-900",
  ];

  const hash = name
    .split("")
    .reduce((acc, char) => acc + char.charCodeAt(0), 0);

  return colors[hash % colors.length];
};

export const truncateText = (text: string, limit: number): string => {
  if (!text) return "";
  if (text.length <= limit) return text;
  return text.substring(0, limit) + "...";
};

// Helper function to get country ISO code from country code number
export const getCountryISOFromCode = (countryCode: string | number): string => {
  const codeMap: { [key: string]: string } = {
    "1": "us",
    "7": "ru",
    "20": "eg",
    "27": "za",
    "30": "gr",
    "31": "nl",
    "32": "be",
    "33": "fr",
    "34": "es",
    "36": "hu",
    "39": "it",
    "40": "ro",
    "41": "ch",
    "43": "at",
    "44": "gb",
    "45": "dk",
    "46": "se",
    "47": "no",
    "48": "pl",
    "49": "de",
    "55": "br",
    "60": "my",
    "61": "au",
    "62": "id",
    "63": "ph",
    "65": "sg",
    "66": "th",
    "81": "jp",
    "84": "vn",
    "86": "cn",
    "90": "tr",
    "91": "in",
    "92": "pk",
    "93": "af",
    "94": "lk",
    "95": "mm",
    "98": "ir",
    "212": "ma",
    "213": "dz",
    "216": "tn",
    "218": "ly",
    "234": "ng",
    "254": "ke",
    "255": "tz",
    "256": "ug",
    "260": "zm",
    "263": "zw",
    "265": "mw",
    "267": "bw",
    "268": "sz",
    "269": "km",
    "290": "sh",
    "291": "er",
    "297": "aw",
    "298": "fo",
    "299": "gl",
    "350": "gi",
    "351": "pt",
    "352": "lu",
    "353": "ie",
    "354": "is",
    "356": "mt",
    "357": "cy",
    "358": "fi",
    "359": "bg",
    "370": "lt",
    "371": "lv",
    "372": "ee",
    "373": "md",
    "374": "am",
    "375": "by",
    "376": "ad",
    "377": "mc",
    "378": "sm",
    "380": "ua",
    "381": "rs",
    "382": "me",
    "383": "xk",
    "385": "hr",
    "386": "si",
    "387": "ba",
    "389": "mk",
    "420": "cz",
    "421": "sk",
    "423": "li",
    "852": "hk",
    "853": "mo",
    "855": "kh",
    "856": "la",
    "880": "bd",
    "886": "tw",
    "960": "mv",
    "961": "lb",
    "962": "jo",
    "963": "sy",
    "964": "iq",
    "965": "kw",
    "966": "sa",
    "967": "ye",
    "968": "om",
    "971": "ae",
    "972": "il",
    "973": "bh",
    "974": "qa",
    "975": "bt",
    "977": "np",
    "992": "tj",
    "993": "tm",
    "994": "az",
    "995": "ge",
    "996": "kg",
    "998": "uz",
  };
  return codeMap[String(countryCode)] || "us";
};

// Helper function to extract phone number without country code
export const extractPhoneNumber = (fullPhone: string): string => {
  if (!fullPhone) return "";

  // Remove all non-digits
  const allDigits = fullPhone.replace(/\D/g, "");

  // Common country codes and their lengths
  const countryCodes = [
    { code: "1", length: 1 }, // US, Canada
    { code: "7", length: 1 }, // Russia
    { code: "20", length: 2 }, // Egypt
    { code: "27", length: 2 }, // South Africa
    { code: "30", length: 2 }, // Greece
    { code: "31", length: 2 }, // Netherlands
    { code: "32", length: 2 }, // Belgium
    { code: "33", length: 2 }, // France
    { code: "34", length: 2 }, // Spain
    { code: "36", length: 2 }, // Hungary
    { code: "39", length: 2 }, // Italy
    { code: "40", length: 2 }, // Romania
    { code: "41", length: 2 }, // Switzerland
    { code: "43", length: 2 }, // Austria
    { code: "44", length: 2 }, // UK
    { code: "45", length: 2 }, // Denmark
    { code: "46", length: 2 }, // Sweden
    { code: "47", length: 2 }, // Norway
    { code: "48", length: 2 }, // Poland
    { code: "49", length: 2 }, // Germany
    { code: "55", length: 2 }, // Brazil
    { code: "60", length: 2 }, // Malaysia
    { code: "61", length: 2 }, // Australia
    { code: "62", length: 2 }, // Indonesia
    { code: "63", length: 2 }, // Philippines
    { code: "65", length: 2 }, // Singapore
    { code: "66", length: 2 }, // Thailand
    { code: "81", length: 2 }, // Japan
    { code: "82", length: 2 }, // South Korea
    { code: "84", length: 2 }, // Vietnam
    { code: "86", length: 2 }, // China
    { code: "90", length: 2 }, // Turkey
    { code: "91", length: 2 }, // India
    { code: "92", length: 2 }, // Pakistan
    { code: "93", length: 2 }, // Afghanistan
    { code: "94", length: 2 }, // Sri Lanka
    { code: "95", length: 2 }, // Myanmar
    { code: "98", length: 2 }, // Iran
    { code: "212", length: 3 }, // Morocco
    { code: "213", length: 3 }, // Algeria
    { code: "216", length: 3 }, // Tunisia
    { code: "218", length: 3 }, // Libya
    { code: "220", length: 3 }, // Gambia
    { code: "221", length: 3 }, // Senegal
    { code: "222", length: 3 }, // Mauritania
    { code: "223", length: 3 }, // Mali
    { code: "224", length: 3 }, // Guinea
    { code: "225", length: 3 }, // Ivory Coast
    { code: "226", length: 3 }, // Burkina Faso
    { code: "227", length: 3 }, // Niger
    { code: "228", length: 3 }, // Togo
    { code: "229", length: 3 }, // Benin
    { code: "230", length: 3 }, // Mauritius
    { code: "231", length: 3 }, // Liberia
    { code: "232", length: 3 }, // Sierra Leone
    { code: "233", length: 3 }, // Ghana
    { code: "234", length: 3 }, // Nigeria
    { code: "235", length: 3 }, // Chad
    { code: "236", length: 3 }, // Central African Republic
    { code: "237", length: 3 }, // Cameroon
    { code: "238", length: 3 }, // Cape Verde
    { code: "239", length: 3 }, // São Tomé and Príncipe
    { code: "240", length: 3 }, // Equatorial Guinea
    { code: "241", length: 3 }, // Gabon
    { code: "242", length: 3 }, // Republic of the Congo
    { code: "243", length: 3 }, // Democratic Republic of the Congo
    { code: "244", length: 3 }, // Angola
    { code: "245", length: 3 }, // Guinea-Bissau
    { code: "246", length: 3 }, // British Indian Ocean Territory
    { code: "247", length: 3 }, // Ascension Island
    { code: "248", length: 3 }, // Seychelles
    { code: "249", length: 3 }, // Sudan
    { code: "250", length: 3 }, // Rwanda
    { code: "251", length: 3 }, // Ethiopia
    { code: "252", length: 3 }, // Somalia
    { code: "253", length: 3 }, // Djibouti
    { code: "254", length: 3 }, // Kenya
    { code: "255", length: 3 }, // Tanzania
    { code: "256", length: 3 }, // Uganda
    { code: "257", length: 3 }, // Burundi
    { code: "258", length: 3 }, // Mozambique
    { code: "260", length: 3 }, // Zambia
    { code: "261", length: 3 }, // Madagascar
    { code: "262", length: 3 }, // Mayotte and Réunion
    { code: "263", length: 3 }, // Zimbabwe
    { code: "264", length: 3 }, // Namibia
    { code: "265", length: 3 }, // Malawi
    { code: "266", length: 3 }, // Lesotho
    { code: "267", length: 3 }, // Botswana
    { code: "268", length: 3 }, // Eswatini
    { code: "269", length: 3 }, // Comoros
    { code: "290", length: 3 }, // Saint Helena
    { code: "291", length: 3 }, // Eritrea
    { code: "297", length: 3 }, // Aruba
    { code: "298", length: 3 }, // Faroe Islands
    { code: "299", length: 3 }, // Greenland
    { code: "350", length: 3 }, // Gibraltar
    { code: "351", length: 3 }, // Portugal
    { code: "352", length: 3 }, // Luxembourg
    { code: "353", length: 3 }, // Ireland
    { code: "354", length: 3 }, // Iceland
    { code: "355", length: 3 }, // Albania
    { code: "356", length: 3 }, // Malta
    { code: "357", length: 3 }, // Cyprus
    { code: "358", length: 3 }, // Finland
    { code: "359", length: 3 }, // Bulgaria
    { code: "370", length: 3 }, // Lithuania
    { code: "371", length: 3 }, // Latvia
    { code: "372", length: 3 }, // Estonia
    { code: "373", length: 3 }, // Moldova
    { code: "374", length: 3 }, // Armenia
    { code: "375", length: 3 }, // Belarus
    { code: "376", length: 3 }, // Andorra
    { code: "377", length: 3 }, // Monaco
    { code: "378", length: 3 }, // San Marino
    { code: "380", length: 3 }, // Ukraine
    { code: "381", length: 3 }, // Serbia
    { code: "382", length: 3 }, // Montenegro
    { code: "383", length: 3 }, // Kosovo
    { code: "385", length: 3 }, // Croatia
    { code: "386", length: 3 }, // Slovenia
    { code: "387", length: 3 }, // Bosnia and Herzegovina
    { code: "389", length: 3 }, // North Macedonia
    { code: "420", length: 3 }, // Czech Republic
    { code: "421", length: 3 }, // Slovakia
    { code: "423", length: 3 }, // Liechtenstein
    { code: "500", length: 3 }, // Falkland Islands
    { code: "501", length: 3 }, // Belize
    { code: "502", length: 3 }, // Guatemala
    { code: "503", length: 3 }, // El Salvador
    { code: "504", length: 3 }, // Honduras
    { code: "505", length: 3 }, // Nicaragua
    { code: "506", length: 3 }, // Costa Rica
    { code: "507", length: 3 }, // Panama
    { code: "508", length: 3 }, // Saint Pierre and Miquelon
    { code: "509", length: 3 }, // Haiti
    { code: "590", length: 3 }, // Guadeloupe
    { code: "591", length: 3 }, // Bolivia
    { code: "592", length: 3 }, // Guyana
    { code: "593", length: 3 }, // Ecuador
    { code: "594", length: 3 }, // French Guiana
    { code: "595", length: 3 }, // Paraguay
    { code: "596", length: 3 }, // Martinique
    { code: "597", length: 3 }, // Suriname
    { code: "598", length: 3 }, // Uruguay
    { code: "599", length: 3 }, // Netherlands Antilles
    { code: "670", length: 3 }, // East Timor
    { code: "672", length: 3 }, // Australian External Territories
    { code: "673", length: 3 }, // Brunei
    { code: "674", length: 3 }, // Nauru
    { code: "675", length: 3 }, // Papua New Guinea
    { code: "676", length: 3 }, // Tonga
    { code: "677", length: 3 }, // Solomon Islands
    { code: "678", length: 3 }, // Vanuatu
    { code: "679", length: 3 }, // Fiji
    { code: "680", length: 3 }, // Palau
    { code: "681", length: 3 }, // Wallis and Futuna
    { code: "682", length: 3 }, // Cook Islands
    { code: "683", length: 3 }, // Niue
    { code: "684", length: 3 }, // American Samoa
    { code: "685", length: 3 }, // Samoa
    { code: "686", length: 3 }, // Kiribati
    { code: "687", length: 3 }, // New Caledonia
    { code: "688", length: 3 }, // Tuvalu
    { code: "689", length: 3 }, // French Polynesia
    { code: "690", length: 3 }, // Tokelau
    { code: "691", length: 3 }, // Micronesia
    { code: "692", length: 3 }, // Marshall Islands
    { code: "850", length: 3 }, // North Korea
    { code: "852", length: 3 }, // Hong Kong
    { code: "853", length: 3 }, // Macau
    { code: "855", length: 3 }, // Cambodia
    { code: "856", length: 3 }, // Laos
    { code: "880", length: 3 }, // Bangladesh
    { code: "886", length: 3 }, // Taiwan
    { code: "960", length: 3 }, // Maldives
    { code: "961", length: 3 }, // Lebanon
    { code: "962", length: 3 }, // Jordan
    { code: "963", length: 3 }, // Syria
    { code: "964", length: 3 }, // Iraq
    { code: "965", length: 3 }, // Kuwait
    { code: "966", length: 3 }, // Saudi Arabia
    { code: "967", length: 3 }, // Yemen
    { code: "968", length: 3 }, // Oman
    { code: "970", length: 3 }, // Palestine
    { code: "971", length: 3 }, // United Arab Emirates
    { code: "972", length: 3 }, // Israel
    { code: "973", length: 3 }, // Bahrain
    { code: "974", length: 3 }, // Qatar
    { code: "975", length: 3 }, // Bhutan
    { code: "976", length: 3 }, // Mongolia
    { code: "977", length: 3 }, // Nepal
    { code: "992", length: 3 }, // Tajikistan
    { code: "993", length: 3 }, // Turkmenistan
    { code: "994", length: 3 }, // Azerbaijan
    { code: "995", length: 3 }, // Georgia
    { code: "996", length: 3 }, // Kyrgyzstan
    { code: "998", length: 3 }, // Uzbekistan
  ];

  // Sort by length (longest first) to match longer country codes first
  const sortedCodes = countryCodes.sort((a, b) => b.length - a.length);

  // Try to find matching country code
  for (const countryCode of sortedCodes) {
    if (allDigits.startsWith(countryCode.code)) {
      // Return the phone number part (without country code)
      return allDigits.substring(countryCode.length);
    }
  }

  // If no country code found, return the full number
  return allDigits;
};

export const formatFileName = (baseName: string) => {
  const now = new Date();
  const day = String(now.getDate()).padStart(2, "0");
  const month = now.toLocaleString("en-US", { month: "short" }); // Aug
  const year = now.getFullYear();
  let hours = now.getHours();
  const minutes = String(now.getMinutes()).padStart(2, "0");
  const ampm = hours >= 12 ? "PM" : "AM";
  hours = hours % 12 || 12;
  const timeStr = `${hours}_${minutes} ${ampm}`;
  return `${baseName} - #${day} ${month} ${year} ${timeStr}.xlsx`;
};

export const getBackendErrorMessage = (
  error: any,
  defaultMessage: string = "An error occurred",
): string => {
  if (!error) return defaultMessage;

  // Check for response.data structure (when success: false in response)
  if (error?.data) {
    // Check for validation errors array (422)
    if (
      error.data?.errors &&
      Array.isArray(error.data.errors) &&
      error.data.errors.length > 0
    ) {
      const firstError = error.data.errors[0];
      return (
        firstError?.message ||
        firstError?.msg ||
        firstError ||
        error.data?.message ||
        defaultMessage
      );
    }

    // Check for message field
    if (error.data?.message) {
      return error.data.message;
    }

    // Check for error object
    if (error.data?.error) {
      if (typeof error.data.error === "string") {
        return error.data.error;
      }
      if (error.data.error?.message) {
        return error.data.error.message;
      }
    }
  }

  // Check for error.response.data structure (network errors)
  if (error?.response?.data) {
    // Check for validation errors array (422)
    if (
      error.response.data?.errors &&
      Array.isArray(error.response.data.errors) &&
      error.response.data.errors.length > 0
    ) {
      const firstError = error.response.data.errors[0];
      return (
        firstError?.message ||
        firstError?.msg ||
        firstError ||
        error.response.data?.message ||
        defaultMessage
      );
    }

    // Check for message field
    if (error.response.data?.message) {
      return error.response.data.message;
    }

    // Check for error object
    if (error.response.data?.error) {
      if (typeof error.response.data.error === "string") {
        return error.response.data.error;
      }
      if (error.response.data.error?.message) {
        return error.response.data.error.message;
      }
    }
  }

  // Fallback to error message or status text
  return error?.message || error?.response?.statusText || defaultMessage;
};

export const formatHoursAndMinutes = (totalHours: number): string => {
  if (!totalHours || totalHours <= 0) return "0 hours 0 minutes";

  const hours = Math.floor(totalHours);
  const minutes = Math.round((totalHours - hours) * 60);

  // handle edge case like 1.999 → 2 hours 0 minutes
  if (minutes === 60) {
    return `${hours + 1} hours 0 minutes`;
  }

  return `${hours} hours ${minutes} minutes`;
};

export const validateNumberInput = (inputValue: any) => {
  const regex = /^[0-9\b]+$/;

  if (inputValue === "" || regex.test(inputValue)) {
    return true;
  }

  return false;
};

export const dateFormate = (dateStr: string): string => {
  try {
    // Check if it's already in DD/MM/YYYY format
    if (/^\d{2}\/\d{2}\/\d{4}$/.test(dateStr)) {
      return dateStr;
    }
    // If it's an ISO date, parse and format it
    return format(parseISO(dateStr), "dd/MM/yyyy");
  } catch (error) {
    return dateStr;
  }
};

const months = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

export const getMonthNumber = (monthName: string) => {
  return months.indexOf(monthName) + 1;
};

export const getMonthFromIndex = (monthIndex: number) => {
  return months[monthIndex - 1];
};

export const getToday = () => {
  const today = new Date();
  const offset = today.getTimezoneOffset();
  const localDate = new Date(today.getTime() - offset * 60 * 1000);
  return localDate.toISOString().split("T")[0];
};
