/**
 * 1688 自动采购 — 前后端共享的搜索管道类型与帮助函数。
 *
 * 这些定义历史上在 `automation/core/types.ts` 与 `src/types/index.ts`
 * 各保留一份且必须保持一致。本模块作为 single source of truth，
 * 由前后端通过 workspace 依赖 `@app/shared-types` 共同消费。
 */

export type SearchFieldType =
  | "primary_search_term"
  | "alt_search_terms"
  | "original_name"
  | "standardized_name"
  | "original_spec"
  | "standardized_spec"
  | "brand"
  | "category"
  | "quantity"
  | "notes";

export interface KeywordCombination {
  fields: SearchFieldType[];
  label: string;
}

export interface SearchPipelineConfig {
  keywordSearchEnabled: boolean;
  imageSearchEnabled: boolean;
  keywordCombinations: KeywordCombination[];
  includeAiKeyword: boolean;
}

export const DEFAULT_SEARCH_PIPELINE_CONFIG: SearchPipelineConfig = {
  keywordSearchEnabled: true,
  imageSearchEnabled: true,
  keywordCombinations: [],
  includeAiKeyword: true,
};

export const SEARCH_FIELD_ORDER: SearchFieldType[] = [
  "primary_search_term",
  "alt_search_terms",
  "original_name",
  "standardized_name",
  "original_spec",
  "standardized_spec",
  "brand",
  "category",
  "quantity",
  "notes",
];

export const SEARCH_FIELD_LABELS: Record<SearchFieldType, string> = {
  primary_search_term: "主搜索词",
  alt_search_terms: "备用搜索词",
  original_name: "原始名称",
  standardized_name: "标准化名称",
  original_spec: "原始规格",
  standardized_spec: "标准化规格",
  brand: "品牌",
  category: "分类(材质/用途)",
  quantity: "数量",
  notes: "备注",
};

const DEFAULT_KEYWORD_COMBINATION_FIELDS: SearchFieldType[] = ["standardized_name"];

const LEGACY_SEARCH_FIELD_MAPPINGS: Record<string, SearchFieldType | null> = {
  name: "standardized_name",
  brand: "brand",
  spec: "standardized_spec",
  parameters: null,
  modifiers: null,
};

export function buildKeywordCombinationLabel(fields: SearchFieldType[]): string {
  return fields.map((field) => SEARCH_FIELD_LABELS[field]).join("+");
}

function toSearchFieldType(field: unknown): SearchFieldType | null {
  const normalized = String(field ?? "").trim();
  if (!normalized) {
    return null;
  }

  if (SEARCH_FIELD_ORDER.includes(normalized as SearchFieldType)) {
    return normalized as SearchFieldType;
  }

  return LEGACY_SEARCH_FIELD_MAPPINGS[normalized] ?? null;
}

export function normalizeKeywordCombinationFields(fields: unknown): SearchFieldType[] {
  const normalizedFields = new Set<SearchFieldType>();

  for (const field of Array.isArray(fields) ? fields : []) {
    const nextField = toSearchFieldType(field);
    if (nextField) {
      normalizedFields.add(nextField);
    }
  }

  return SEARCH_FIELD_ORDER.filter((field) => normalizedFields.has(field));
}

export function createDefaultKeywordCombination(): KeywordCombination {
  return {
    fields: [...DEFAULT_KEYWORD_COMBINATION_FIELDS],
    label: buildKeywordCombinationLabel(DEFAULT_KEYWORD_COMBINATION_FIELDS),
  };
}

export function normalizeKeywordCombination(value: unknown): KeywordCombination | null {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    return null;
  }

  const record = value as Record<string, unknown>;
  const rawFields = Array.isArray(record.fields) ? record.fields : [];
  const fields = normalizeKeywordCombinationFields(rawFields);
  const effectiveFields = fields.length > 0
    ? fields
    : rawFields.length > 0
      ? [...DEFAULT_KEYWORD_COMBINATION_FIELDS]
      : [];

  if (effectiveFields.length === 0) {
    return null;
  }

  return {
    fields: effectiveFields,
    label: buildKeywordCombinationLabel(effectiveFields),
  };
}

export function normalizeSearchPipelineConfig(value: unknown): SearchPipelineConfig {
  const candidate = value && typeof value === "object" && !Array.isArray(value)
    ? value as Record<string, unknown>
    : {};

  const keywordCombinations = (() => {
    if (!Array.isArray(candidate.keywordCombinations)) {
      return [...DEFAULT_SEARCH_PIPELINE_CONFIG.keywordCombinations];
    }

    const combinations: KeywordCombination[] = [];
    const seen = new Set<string>();

    for (const entry of candidate.keywordCombinations) {
      const normalized = normalizeKeywordCombination(entry);
      if (!normalized) {
        continue;
      }

      const signature = normalized.fields.join("|");
      if (seen.has(signature)) {
        continue;
      }

      seen.add(signature);
      combinations.push(normalized);
    }

    return combinations;
  })();

  return {
    keywordSearchEnabled: typeof candidate.keywordSearchEnabled === "boolean"
      ? candidate.keywordSearchEnabled
      : DEFAULT_SEARCH_PIPELINE_CONFIG.keywordSearchEnabled,
    imageSearchEnabled: typeof candidate.imageSearchEnabled === "boolean"
      ? candidate.imageSearchEnabled
      : DEFAULT_SEARCH_PIPELINE_CONFIG.imageSearchEnabled,
    includeAiKeyword: typeof candidate.includeAiKeyword === "boolean"
      ? candidate.includeAiKeyword
      : DEFAULT_SEARCH_PIPELINE_CONFIG.includeAiKeyword,
    keywordCombinations,
  };
}
