// Helper functions for input masks and validations

/** Remove all non-digit characters from string */
export const onlyDigits = (value: string): string => {
  return (value || "").replace(/\D/g, "");
};

/** Format CPF: 000.000.000-00 */
export const maskCPF = (value: string): string => {
  const digits = onlyDigits(value).slice(0, 11);
  return digits
    .replace(/(\d{3})(\d)/, "$1.$2")
    .replace(/(\d{3})(\d)/, "$1.$2")
    .replace(/(\d{3})(\d{1,2})$/, "$1-$2");
};

/** Validate CPF format and checksum */
export const validateCPF = (value: string): boolean => {
  const digits = onlyDigits(value);
  
  if (digits.length !== 11 || /^([0-9])\1+$/.test(digits)) {
    return false;
  }
  
  const calculateDigit = (base: string, factor: number): number => {
    let sum = 0;
    for (let i = 0; i < base.length; i++) {
      sum += parseInt(base[i]) * (factor - i);
    }
    const rest = (sum * 10) % 11;
    return rest === 10 ? 0 : rest;
  };
  
  const digit1 = calculateDigit(digits.slice(0, 9), 10);
  const digit2 = calculateDigit(digits.slice(0, 10), 11);
  
  return digits[9] === String(digit1) && digits[10] === String(digit2);
};

/** Format CEP: 00000-000 */
export const maskCEP = (value: string): string => {
  const digits = onlyDigits(value).slice(0, 8);
  return digits.replace(/(\d{5})(\d{1,3})$/, "$1-$2");
};

/** Format phone: (00) 0000-0000 or (00) 00000-0000 */
export const maskPhone = (value: string): string => {
  const digits = onlyDigits(value).slice(0, 11);
  
  if (digits.length <= 10) {
    return digits
      .replace(/(\d{2})(\d)/, "($1) $2")
      .replace(/(\d{4})(\d{1,4})$/, "$1-$2");
  }
  
  return digits
    .replace(/(\d{2})(\d)/, "($1) $2")
    .replace(/(\d{5})(\d{1,4})$/, "$1-$2");
};

/** Format date: dd/mm/aaaa */
export const maskDate = (value: string): string => {
  const digits = onlyDigits(value).slice(0, 8);
  return digits
    .replace(/(\d{2})(\d)/, "$1/$2")
    .replace(/(\d{2})(\d{1,4})$/, "$1/$2");
};

/** Validate date in format dd/mm/aaaa */
export const validateDate = (value: string): boolean => {
  const match = value.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
  if (!match) return false;
  
  const day = Number(match[1]);
  const month = Number(match[2]) - 1;
  const year = Number(match[3]);
  
  const date = new Date(year, month, day);
  
  return (
    date.getFullYear() === year &&
    date.getMonth() === month &&
    date.getDate() === day
  );
};

/** Format UF: uppercase, max 2 chars */
export const maskUF = (value: string): string => {
  return (value || "").toUpperCase().replace(/[^A-Z]/g, "").slice(0, 2);
};

/** Format RG by UF */
const rgFormatByUF: Record<string, [number, number, number, number]> = {
  RJ: [2, 3, 2, 1],
  SP: [2, 3, 3, 1],
  MG: [2, 3, 3, 1],
  ES: [2, 3, 3, 1],
  PR: [2, 3, 3, 1],
  SC: [2, 3, 3, 1],
  RS: [2, 3, 3, 1],
  BA: [2, 3, 3, 1],
  PE: [2, 3, 3, 1],
  CE: [2, 3, 3, 1],
  PA: [2, 3, 3, 1],
  AM: [2, 3, 3, 1],
  AC: [2, 3, 3, 1],
  AP: [2, 3, 3, 1],
  AL: [2, 3, 3, 1],
  RN: [2, 3, 3, 1],
  PB: [2, 3, 3, 1],
  MA: [2, 3, 3, 1],
  PI: [2, 3, 3, 1],
  DF: [2, 3, 3, 1],
  GO: [2, 3, 3, 1],
  MT: [2, 3, 3, 1],
  MS: [2, 3, 3, 1],
  RO: [2, 3, 3, 1],
  RR: [2, 3, 3, 1],
  TO: [2, 3, 3, 1],
};

export const maskRGByUF = (uf: string, value: string): string => {
  const raw = (value || "").toUpperCase().replace(/[^0-9X]/g, "");
  const [a, b, c, dv] = rgFormatByUF[uf?.toUpperCase()] ?? [2, 3, 3, 1];
  const baseMax = a + b + c;
  const baseDigits = raw.replace(/X/g, "").slice(0, baseMax);
  const verifier = raw.slice(baseDigits.length, baseDigits.length + dv).slice(0, 1);
  
  const g1 = baseDigits.slice(0, a);
  const g2 = baseDigits.slice(a, a + b);
  const g3 = baseDigits.slice(a + b, a + b + c);
  
  let formatted = g1;
  if (g2) formatted += `.${g2}`;
  if (g3) formatted += `.${g3}`;
  if (verifier) formatted += `-${verifier}`;
  
  return formatted;
};

export const padRGLeftByUF = (uf: string, value: string): string => {
  const raw = (value || "").toUpperCase().replace(/[^0-9X]/g, "");
  const [a, b, c, dv] = rgFormatByUF[uf?.toUpperCase()] ?? [2, 3, 3, 1];
  const baseMax = a + b + c;
  let base = raw.replace(/X/g, "");
  const verifier = raw.slice(base.length, base.length + dv).slice(0, 1);
  
  if (base.length < baseMax) {
    base = base.padStart(baseMax, "0");
  }
  
  return maskRGByUF(uf, base + (verifier || ""));
};

/** Format account number */
export const maskContaBancaria = (value: string): string => {
  const digits = onlyDigits(value);
  return digits;
};

/** Format zone and section for voter title */
export const maskZonaSecao = (value: string): string => {
  const digits = onlyDigits(value).slice(0, 4);
  return digits;
};

/** Format general numeric field */
export const maskNumeric = (value: string): string => {
  return onlyDigits(value);
};

/** Remove extra spaces and trim */
export const normalizeText = (value: string): string => {
  return (value || "").replace(/\s+/g, " ").trim();
};

