import { useI18n } from "vue-i18n";

/**
 * @description Corta uma string em um determinado tamanho.
 * @param {string} string string a ser cortada.
 * @param {string} size tamanho da string.
 * @returns {string} string cortada.
 */
const excerpt = (string, size = 30) => {
  if (size == null) return string;
  if (string.length > size) {
    string = string.substring(0, size) + "...";
  }
  return string;
};

/**
 * @description Formata uma data de DD/MM/YYYY para YYYY-MM-DD
 * @param {string} date data.
 * @param {string} time tempo.
 * @throws {Error} Caso a data seja nula ou invalida.
 * @returns {string} data formatada.
 */
const formatDateDMYtoYMD = (date, time) => {
  if (!date) throw new Error(useI18n().t("validation.rules.required"));
  const testDate =
    /^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$/;
  if (testDate.test(date) === false)
    throw new Error(useI18n().t("validation.rules.date"));

  const [day, month, year] = date.split("/");
  return `${year}-${month}-${day} ${time ? time : ""}`;
};

/**
 * @description Converte uma data e hora para o formato brasileiro.
 * @param {string} dateTimeString data e hora.
 * @returns {string} data e hora no formato brasileiro.
 * @throws {Error} Caso a data seja nula ou invalida.
 * @returns {string} data formatada.
 * @example
 * // convertDateTime("2023-05-23T13:07:27.000000Z");
 * // Output: 23/05/2023 10:07:27
 */
const convertDateTime = (dateTimeString) => {
  const dateTime = new Date(dateTimeString);
  const options = {
    timeZone: "America/Sao_Paulo",
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  };
  const formattedDateTime = dateTime
    .toLocaleString("pt-BR", options)
    .replace(",", "");
  return formattedDateTime;
};

/**
 * @description Formata uma data de YYYY-MM-DD para DD/MM/YYYY
 * @param {string} dateTime data e hora.
 * @returns {string} data e hora no formato brasileiro.
 * @example
 * // formatDateYMDtoDMY("2023-05-23T13:07:27.000000Z");
 * // Output: 23/05/2023 10:07:27
 */
const formatDateYMDtoDMY = (dateTime) => {
  const [datePart, timePart] = dateTime.split(" ");
  const [year, month, day] = datePart.split("-");
  const formattedDate = `${day}/${month}/${year}`;
  if (timePart) {
    const [hours, minutes, seconds] = timePart.split(":");
    const formattedTime = `${hours}:${minutes}:${seconds}`;
    return `${formattedDate} ${formattedTime}`;
  }
  return formattedDate;
};

/**
 * @description Checa a moeda selecionada.
 * @param {number} moeda moeda selecionada.
 * @returns {object} opções de moeda.
 */
const checaMoeda = (moeda) => {
  let currencyOptions = {};
  if (moeda == 1) {
    currencyOptions = {
      locale: "pt-BR",
      currency: "BRL",
      currencyDisplay: "symbol",
      hideCurrencySymbolOnFocus: false,
      hideGroupingSeparatorOnFocus: false,
      hideNegligibleDecimalDigitsOnFocus: false,
      autoDecimalDigits: true,
      useGrouping: true,
      accountingSign: false,
    };
  } else if (moeda == 2) {
    currencyOptions = {
      currency: "PYG",
      locale: "es-PY",
      valueAsInteger: true,
      distractionFree: true,
      precision: 0,
      autoDecimalMode: true,
      valueRange: { min: 0 },
      allowNegative: true,
    };
  } else if (moeda == 3) {
    currencyOptions = {
      locale: "en-US",
      currency: "USD",
      currencyDisplay: "symbol",
      hideCurrencySymbolOnFocus: true,
      hideGroupingSeparatorOnFocus: true,
      hideNegligibleDecimalDigitsOnFocus: false,
      autoDecimalDigits: true,
      useGrouping: true,
      accountingSign: false,
    };
  }
  return currencyOptions;
};

/**
 * @description Filtra a moeda.
 * @param {number} value valor.
 * @returns {string} valor formatado.
 */
const filterCurrency = (value) => {
  if (value) {
    value = parseFloat(value);
    return value.toLocaleString("pt-BR", {
      style: "currency",
      currency: "BRL",
    });
  }
  return value;
};

/**
 * @description Filtra a unidade de medida.
 * @param {number} value valor.
 * @returns {string} valor formatado.
 */
const filterUnidadeMedida = (value) => {
  return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
};

/**
 * @description Valida se a data é válida.
 * @param {string} date data.
 * @returns {boolean} true se a data é válida, false caso contrário.
 */
const validaData = (date) => {
  const regex = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/;
  return regex.test(date);
};

/**
 * @description Valida se a hora é válida.
 * @param {string} time hora.
 * @returns {boolean} true se a hora é válida, false caso contrário.
 */
const validaHora = (time) => {
  const regex = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/;
  return regex.test(time);
};

/**
 * @description Valida se a data e hora são válidas.
 * @param {string} dataHora data e hora.
 * @returns {boolean} true se a data e hora são válidas, false caso contrário.
 */
const validaDataHora = (dataHora) => {
  const regex =
    /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}\s([0-1][0-9]|2[0-3]):[0-5][0-9]$/;
  return regex.test(dataHora);
};

/**
 * @description Formata a quantidade.
 * @param {number} value valor.
 * @returns {string} valor formatado.
 */
const formatQuantity = (value) => {
  if (value) {
    return value
      .toString()
      .replace(/[^0-9]/g, "")
      .replace(/\B(?=(\d{3})+(?!\d))/g, ".");
  }
  return value;
};

/**
 * @description Formata a moeda.
 * @param {number} value valor.
 * @returns {string} valor formatado.
 */
const formatCurrency = (value) => {
  if (value != null) {
    value = parseFloat(value);
    return value.toLocaleString("pt-BR", {
      minimumFractionDigits: 2,
      style: "currency",
      currency: "BRL",
    });
  }
  return value;
};

// algoritmo de luhn que valida se o cartao tem numero valido (nao garante que ele existe, só garante que poderia ser um numero de cartao realmente valido)
const validateCardNumberLuhn = (cardNumber) => {
  const digits = cardNumber.replace(/\D/g, '');

  if (digits.length < 13 || digits.length > 19) return false;

  let sum = 0;
  let isEven = false;

  for (let i = digits.length - 1; i >= 0; i--) {
    let digit = parseInt(digits[i], 10);

    if (isEven) {
      digit *= 2;
      if (digit > 9) digit -= 9;
    }

    sum += digit;
    isEven = !isEven;
  }

  return sum % 10 === 0;
};

const detectCardBrand = (cardNumber) => {
  const digits = (cardNumber || '').replace(/\D/g, '');

  if (!digits) return null;

  // Visa
  if (/^4/.test(digits)) return 'visa';

  // Mastercard (inclui range novo 2221–2720)
  if (/^(5[1-5]|2[2-7][0-9]{2})/.test(digits)) return 'mastercard';

  // Elo (principais BINs conhecidos)
  if (/^(4011|4312|4389|4514|4576|5041|5066|5067|5090|6277|6362|6363|6504|6505|6516|6550)/.test(digits)) return 'elo';

  // Hipercard
  if (/^(3841|60)/.test(digits)) return 'hipercard';

  // American Express
  if (/^3[47]/.test(digits)) return 'amex';

  // Diners Club
  if (/^(30[0-5]|36|38|39)/.test(digits)) return 'diners';

  // Discover
  if (/^(6011|65|64[4-9])/.test(digits)) return 'discover';

  // JCB
  if (/^35/.test(digits)) return 'jcb';

  // Aura (Banco do Brasil)
  if (/^50/.test(digits)) return 'aura';

  return null;
};

const validateCardExpiration = (expiration) => {
  if (!expiration || !/^\d{2}\/\d{4}$/.test(expiration)) return false;
  const [month, year] = expiration.split('/').map(Number);
  if (month < 1 || month > 12) return false;
  const now = new Date();
  const currentYear = now.getFullYear();
  const currentMonth = now.getMonth() + 1;
  if (year < currentYear) return false;
  if (year === currentYear && month < currentMonth) return false;
  return true;
};

const formatAddress = (address) => {
  if (!address) return '';
  const { address: street, number, district, city, state } = address;
  let parts = [];
  if (street && street !== null && street != 'null') parts.push(street);
  if (number && number !== null && number != 'null') parts.push(number);
  if (district && district !== null && district != 'null') parts.push(district);
  if (city?.name && city.name !== null && city.name != 'null') parts.push(city.name);
  if (state?.code && state.code !== null && state.code != 'null') parts.push(state.code);
  return parts.join(', ');
};

const getFirstName = (fullName) => {
  if (!fullName) return '';

  return String(fullName)
    .trim()
    .split(/\s+/)[0];
};

const calculateDailyPrices = (dailyPrice8h) => {
  if (!dailyPrice8h || dailyPrice8h <= 0) {
    return {
      daily_price_8h: null,
      daily_price_6h: null,
      daily_price_4h: null,
      daily_price_2h: null,
    };
  }

  return {
    daily_price_8h: dailyPrice8h,
    daily_price_6h: dailyPrice8h * 0.85,
    daily_price_4h: dailyPrice8h * 0.55,
    daily_price_2h: dailyPrice8h * 0.30,
  };
};

const chooseprice = (periodType, daily_price_8h) => {
  let alldaily_prices = calculateDailyPrices(daily_price_8h);
  switch (periodType) {
    case "8":
      return daily_price_8h
    case "6":
      return alldaily_prices.daily_price_6h
    case "4":
      return alldaily_prices.daily_price_4h
    case "2":
      return alldaily_prices.daily_price_2h
    default:
      return 0
  }

};

const formatLabelByPeriodType = (type) => {
  switch (type) {
    case '2': return useI18n().t('period_types.2');
    case '4': return useI18n().t('period_types.4');
    case '6': return useI18n().t('period_types.6');
    case '8': return useI18n().t('period_types.8');
    default: return useI18n().t('period_types.unknown');

  }
};

export {
  formatDateDMYtoYMD,
  formatDateYMDtoDMY,
  excerpt,
  convertDateTime,
  checaMoeda,
  filterCurrency,
  filterUnidadeMedida,
  validaData,
  validaHora,
  validaDataHora,
  formatQuantity,
  formatCurrency,
  validateCardNumberLuhn,
  detectCardBrand,
  validateCardExpiration,
  formatAddress,
  getFirstName,
  calculateDailyPrices,
  chooseprice,
  formatLabelByPeriodType
};
