import type { SkillCatalogItem } from "@qjclaw/shared-types";

export interface SkillTriggerMatch {
  query: string;
  start: number;
  end: number;
}

export function normalizeSkillSearch(value: string): string {
  return value
    .normalize("NFKC")
    .toLowerCase()
    .replace(/[^\p{L}\p{N}\s-]+/gu, " ")
    .replace(/\s+/g, " ")
    .trim();
}

export function findSkillTriggerMatch(value: string, cursor: number): SkillTriggerMatch | null {
  const normalizedCursor = Math.max(0, Math.min(cursor, value.length));
  const prefix = value.slice(0, normalizedCursor);
  const match = prefix.match(/(?:^|[\s(（【\[{'""'])@([^\s@]*)$/u);
  if (!match) {
    return null;
  }

  const raw = match[0];
  const atOffset = raw.lastIndexOf("@");
  if (atOffset < 0) {
    return null;
  }

  return {
    query: match[1] ?? "",
    start: prefix.length - raw.length + atOffset,
    end: normalizedCursor
  };
}

export function stripSkillTriggerFromPrompt(value: string, trigger: SkillTriggerMatch | null): string {
  if (!trigger) {
    return value;
  }

  const next = `${value.slice(0, trigger.start)}${value.slice(trigger.end)}`;
  return next.replace(/[ \t]{2,}/g, " ").replace(/\n{3,}/g, "\n\n");
}

export interface ResolvePromptSkillResult {
  cleanPrompt: string;
  resolvedSkillId: string | undefined;
  error?: string;
}

function findSkillTriggerInFullText(value: string): SkillTriggerMatch | null {
  const match = value.match(/(?:^|[\s(（【\[{'""'])@([^\s@]+)/u);
  if (!match || !match[1]) {
    return null;
  }
  const raw = match[0];
  const atOffset = raw.lastIndexOf("@");
  const start = (match.index ?? 0) + atOffset;
  return {
    query: match[1],
    start,
    end: start + 1 + match[1].length
  };
}

export function resolvePromptSkill(
  promptText: string,
  catalog: SkillCatalogItem[]
): ResolvePromptSkillResult {
  const trigger = findSkillTriggerInFullText(promptText);
  if (!trigger || !trigger.query) {
    return { cleanPrompt: promptText, resolvedSkillId: undefined };
  }

  const q = trigger.query.toLowerCase();
  const selectables = catalog.filter((s) => s.selectable);

  const matches = selectables.filter(
    (s) =>
      s.zhName.toLowerCase() === q ||
      s.name.toLowerCase() === q ||
      normalizeSkillSearch(s.searchText).split(/\s+/).includes(q)
  );

  if (matches.length === 0) {
    return {
      cleanPrompt: promptText,
      resolvedSkillId: undefined,
      error: `未找到可用技能「${trigger.query}」，请从弹层中选择`
    };
  }

  if (matches.length > 1) {
    return {
      cleanPrompt: promptText,
      resolvedSkillId: undefined,
      error: `「${trigger.query}」匹配到多个技能，请从弹层中明确选择`
    };
  }

  return {
    cleanPrompt: stripSkillTriggerFromPrompt(promptText, trigger),
    resolvedSkillId: matches[0]!.id
  };
}
