import type { Project } from "@/lib/store";
import { canonicalOptionLabel, dedupeOptions, normalizeOptionKey } from "@/lib/optionUtils";

const COUNTRY_ALIASES: Record<string, string> = {
  cr: "Costa Rica",
  "costa rica": "Costa Rica",
  costarica: "Costa Rica",
  gt: "Guatemala",
  gua: "Guatemala",
  guate: "Guatemala",
  guatemala: "Guatemala",
  hn: "Honduras",
  honduras: "Honduras",
  ni: "Nicaragua",
  nicaragua: "Nicaragua",
  sv: "El Salvador",
  es: "El Salvador",
  "el salvador": "El Salvador",
  elsalvador: "El Salvador",
  pa: "Panama",
  pty: "Panama",
  panama: "Panama",
  rd: "Republica Dominicana",
  repdom: "Republica Dominicana",
  "republica dominicana": "Republica Dominicana",
  republicadominicana: "Republica Dominicana",
  do: "Republica Dominicana",
  mx: "Mexico",
  mexico: "Mexico",
  pr: "Puerto Rico",
  "puerto rico": "Puerto Rico",
  puertorico: "Puerto Rico",
  co: "Colombia",
  colombia: "Colombia",
  jm: "Jamaica",
  jamaica: "Jamaica",
  tt: "Trinidad",
  trinidad: "Trinidad",
  ve: "Venezuela",
  venezuela: "Venezuela",
  latam: "Latam",
  wmc: "WMC",
};

const COUNTRY_CODE_PATTERNS: Array<[RegExp, string]> = [
  [/(^|[_\-\s])cr([_\-\s]|$)/i, "Costa Rica"],
  [/(^|[_\-\s])(gt|gua|guate)([_\-\s]|$)/i, "Guatemala"],
  [/(^|[_\-\s])hn([_\-\s]|$)/i, "Honduras"],
  [/(^|[_\-\s])ni([_\-\s]|$)/i, "Nicaragua"],
  [/(^|[_\-\s])(sv|es)([_\-\s]|$)/i, "El Salvador"],
  [/(^|[_\-\s])(pa|pty|panama)([_\-\s]|$)/i, "Panama"],
  [/(^|[_\-\s])(rd|repdom|do)([_\-\s]|$)/i, "Republica Dominicana"],
  [/(^|[_\-\s])mx([_\-\s]|$)/i, "Mexico"],
  [/(^|[_\-\s])pr([_\-\s]|$)/i, "Puerto Rico"],
  [/(^|[_\-\s])co([_\-\s]|$)/i, "Colombia"],
  [/(^|[_\-\s])jm([_\-\s]|$)/i, "Jamaica"],
  [/(^|[_\-\s])tt([_\-\s]|$)/i, "Trinidad"],
  [/(^|[_\-\s])ve([_\-\s]|$)/i, "Venezuela"],
  [/(^|[_\-\s])latam([_\-\s]|$)/i, "Latam"],
  [/(^|[_\-\s])wmc([_\-\s]|$)/i, "WMC"],
];

function clean(value: unknown) {
  return canonicalOptionLabel(String(value ?? ""));
}

function addCanonicalToken(tokens: string[], value: unknown, knownOptions: string[] = []) {
  const label = clean(value);
  if (!label) return;

  const known = knownOptions.find(
    (option) => normalizeOptionKey(option) === normalizeOptionKey(label),
  );
  tokens.push(known || label);
}

function addKnownOptionsContained(tokens: string[], value: unknown, knownOptions: string[]) {
  const label = clean(value);
  const valueKey = normalizeOptionKey(label);
  if (!valueKey) return;

  knownOptions.forEach((option) => {
    const optionKey = normalizeOptionKey(option);
    if (!optionKey) return;
    if (valueKey === optionKey || valueKey.includes(optionKey)) {
      tokens.push(option);
    }
  });
}

export function splitMultiValueTokens(value: unknown, knownOptions: string[] = []) {
  const label = clean(value);
  if (!label) return [];

  const tokens: string[] = [];
  addKnownOptionsContained(tokens, label, knownOptions);

  label
    .split(/[,;|/]+/)
    .map((part) => clean(part))
    .filter(Boolean)
    .forEach((part) => addCanonicalToken(tokens, part, knownOptions));

  if (tokens.length === 0) addCanonicalToken(tokens, label, knownOptions);

  return dedupeOptions(tokens);
}

export function getCountryTokensFromText(value: unknown, knownCountries: string[] = []) {
  const label = clean(value);
  if (!label) return [];

  const tokens: string[] = [];
  addKnownOptionsContained(tokens, label, knownCountries);

  label
    .split(/[,;|/]+/)
    .map((part) => clean(part))
    .filter(Boolean)
    .forEach((part) => {
      const alias = COUNTRY_ALIASES[normalizeOptionKey(part)];
      const known = knownCountries.find(
        (country) => normalizeOptionKey(country) === normalizeOptionKey(part),
      );

      if (alias) tokens.push(alias);
      else if (known) tokens.push(known);
    });

  COUNTRY_CODE_PATTERNS.forEach(([pattern, country]) => {
    if (pattern.test(label)) tokens.push(country);
  });

  // Importante: para país NO hacemos fallback al texto completo.
  // La data histórica contiene títulos/observaciones en campos mezclados;
  // si agregamos el texto bruto como opción, el dropdown de País se contamina
  // con frases como "AF 03...", "Rep Dom Lizbeth", etc.
  return dedupeOptions(tokens);
}

export function getProjectCountryTokens(project: Project, knownCountries: string[] = []) {
  const tokens = [
    ...getCountryTokensFromText(project.bu, knownCountries),
    ...getCountryTokensFromText(project.nombre, knownCountries),
  ];

  const clientKey = normalizeOptionKey(project.cliente);
  const titleKey = normalizeOptionKey(project.nombre);

  if (
    clientKey.includes("walmartconnect") ||
    clientKey.includes("wmc") ||
    titleKey.includes("wmc")
  ) {
    tokens.push("WMC");
  }

  return dedupeOptions(tokens);
}

export function getProjectBrandTokens(project: Project, knownBrands: string[] = []) {
  return splitMultiValueTokens(project.marca, knownBrands);
}

export function getProjectClientTokens(project: Project, knownClients: string[] = []) {
  return splitMultiValueTokens(project.cliente, knownClients);
}

export function getProjectCmTokens(project: Project, knownCms: string[] = []) {
  return splitMultiValueTokens(project.cm, knownCms);
}

function tokenMatches(tokens: string[], filter: string) {
  const filterKey = normalizeOptionKey(filter);
  if (!filterKey) return true;

  return tokens.some((token) => {
    const tokenKey = normalizeOptionKey(token);
    return tokenKey === filterKey || tokenKey.includes(filterKey) || filterKey.includes(tokenKey);
  });
}

export function projectMatchesSmartFilters(
  project: Project,
  filters: { country?: string; brand?: string; client?: string; cm?: string },
  options: { countries?: string[]; brands?: string[]; clients?: string[]; cms?: string[] } = {},
) {
  if (filters.country) {
    const countryTokens = getProjectCountryTokens(project, options.countries || []);
    if (!tokenMatches(countryTokens, filters.country)) return false;
  }

  if (filters.brand) {
    const brandTokens = getProjectBrandTokens(project, options.brands || []);
    if (!tokenMatches(brandTokens, filters.brand)) return false;
  }

  if (filters.client) {
    const clientTokens = getProjectClientTokens(project, options.clients || []);
    if (!tokenMatches(clientTokens, filters.client)) return false;
  }

  if (filters.cm) {
    const cmTokens = getProjectCmTokens(project, options.cms || []);
    if (!tokenMatches(cmTokens, filters.cm)) return false;
  }

  return true;
}

export function expandCountryOptions(values: string[], knownCountries: string[] = []) {
  return dedupeOptions(values.flatMap((value) => getCountryTokensFromText(value, knownCountries)));
}

export function expandMultiValueOptions(values: string[], knownOptions: string[] = []) {
  return dedupeOptions(values.flatMap((value) => splitMultiValueTokens(value, knownOptions)));
}

export function buildSmartFilterOptionsFromProjects(
  projects: Project[],
  options: { countries?: string[]; brands?: string[]; clients?: string[]; cms?: string[] } = {},
) {
  return {
    countries: dedupeOptions(
      projects.flatMap((project) => getProjectCountryTokens(project, options.countries || [])),
    ),
    brands: dedupeOptions(
      projects.flatMap((project) => getProjectBrandTokens(project, options.brands || [])),
    ),
    clients: dedupeOptions(
      projects.flatMap((project) => getProjectClientTokens(project, options.clients || [])),
    ),
    cms: dedupeOptions(
      projects.flatMap((project) => getProjectCmTokens(project, options.cms || [])),
    ),
  };
}

export function hasSmartFilter(filters: {
  country?: string;
  brand?: string;
  client?: string;
  cm?: string;
}) {
  return Boolean(filters.country || filters.brand || filters.client || filters.cm);
}
