import {
  BUILTIN_SEARCH_TEMPLATES,
  type KeywordCombination,
  normalizeSearchPipelineConfig,
  type SearchPipelineConfig,
  type SearchPreset,
} from '@/types';

function areFieldListsEqual(left: string[], right: string[]) {
  return left.length === right.length && left.every((field, index) => field === right[index]);
}

function areKeywordCombinationsEqual(left: KeywordCombination[], right: KeywordCombination[]) {
  return left.length === right.length && left.every((combination, index) => {
    const other = right[index];
    return Boolean(other) && areFieldListsEqual(combination.fields, other.fields);
  });
}

export function areSearchPipelineConfigsEqual(left: SearchPipelineConfig, right: SearchPipelineConfig) {
  const normalizedLeft = normalizeSearchPipelineConfig(left);
  const normalizedRight = normalizeSearchPipelineConfig(right);

  return (
    normalizedLeft.keywordSearchEnabled === normalizedRight.keywordSearchEnabled
    && normalizedLeft.imageSearchEnabled === normalizedRight.imageSearchEnabled
    && normalizedLeft.includeAiKeyword === normalizedRight.includeAiKeyword
    && areKeywordCombinationsEqual(normalizedLeft.keywordCombinations, normalizedRight.keywordCombinations)
  );
}

function matchesBuiltinTemplate(config: SearchPipelineConfig, templateId: string) {
  const builtin = BUILTIN_SEARCH_TEMPLATES.find(template => template.id === templateId);
  if (!builtin) return false;

  return areKeywordCombinationsEqual(
    normalizeSearchPipelineConfig(builtin.config).keywordCombinations,
    normalizeSearchPipelineConfig(config).keywordCombinations,
  );
}

function matchesPreset(config: SearchPipelineConfig, presetId: string, presets: SearchPreset[]) {
  const preset = presets.find(item => item.id === presetId);
  if (!preset) return false;

  return areSearchPipelineConfigsEqual(preset.config, config);
}

function matchesCustomTemplate(config: SearchPipelineConfig, presets: SearchPreset[]) {
  const matchesPresetConfig = presets.some(preset => areSearchPipelineConfigsEqual(preset.config, config));
  if (matchesPresetConfig) return false;

  return !BUILTIN_SEARCH_TEMPLATES.some(template => (
    areKeywordCombinationsEqual(
      normalizeSearchPipelineConfig(template.config).keywordCombinations,
      normalizeSearchPipelineConfig(config).keywordCombinations,
    )
  ));
}

function templateMatchesConfig(
  templateId: string,
  config: SearchPipelineConfig,
  presets: SearchPreset[],
) {
  if (templateId === 'custom') {
    return matchesCustomTemplate(config, presets);
  }

  return matchesPreset(config, templateId, presets) || matchesBuiltinTemplate(config, templateId);
}

export function resolveSearchTemplateId(
  config: SearchPipelineConfig,
  presets: SearchPreset[],
  preferredTemplateId?: string,
) {
  const normalizedConfig = normalizeSearchPipelineConfig(config);

  if (preferredTemplateId && templateMatchesConfig(preferredTemplateId, config, presets)) {
    return preferredTemplateId;
  }

  const presetMatch = presets.find(preset => areSearchPipelineConfigsEqual(preset.config, normalizedConfig));
  if (presetMatch) {
    return presetMatch.id;
  }

  const builtinMatch = BUILTIN_SEARCH_TEMPLATES.find(template => (
    areKeywordCombinationsEqual(
      normalizeSearchPipelineConfig(template.config).keywordCombinations,
      normalizedConfig.keywordCombinations,
    )
  ));
  if (builtinMatch) {
    return builtinMatch.id;
  }

  return 'custom';
}

export function shouldShowAdvancedSearchTemplate(templateId: string, presets: SearchPreset[]) {
  if (templateId === 'custom') return true;

  const preset = presets.find(item => item.id === templateId);
  return Boolean(preset && preset.config.keywordCombinations.length > 0);
}