/**
 * Skills + Examples lookup MCP tools — LI SDD M3.2 / M3.4
 *
 * 對應 docs/3-specs/llm-interface/ Milestone 3.2 + 3.4。
 *
 * - arcrun_list_skills      — 列 KBDB entry_type=agent-skill 全部
 * - arcrun_get_skill        — 用 slug 拿 skill markdown 全文
 * - arcrun_list_examples    — 列 KBDB entry_type=workflow-example 全部
 * - arcrun_get_example      — 用 slug 拿 example yaml + description + tags
 * - arcrun_search_examples  — use case 關鍵字 → 命中相關 example
 *
 * Skills / examples 由 arcrun/scripts/sync-registry-to-kbdb.py 從
 * arcrun/registry/{skills,examples} 同步進 KBDB。
 *
 * 直接走 KBDB service binding（既有 pattern），不經 cypher-executor。
 *
 * 2026-06-14 重寫：KBDB 降基本盤後（三表 entries/templates/records，無 v3 blocks 表、
 * 無語義 search），原打 /blocks /search 的舊路徑全失效。改打基本盤 /entries：
 *   - entry_type 取代 blocks 的 type 欄（entries 表原生有 entry_type/page_name/tags_json/metadata_json）
 *   - GET /blocks?type=X       → GET /entries?entry_type=X
 *   - GET /blocks?page_name=Y  → GET /entries?page_name=Y（base listEntries 加了 page_name 過濾）
 *   - POST /search（語義）      → GET /entries/search?q=（D1 LIKE 關鍵字，基本盤無語義；
 *       誠實降級：search_examples 現在是「關鍵字」非「語義」。embed 模組（kbdb-base Phase 1）
 *       上線後只換內部、工具簽名不變。
 */

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { toolName } from "../brand.js";
import { z } from "zod";
import type { Env } from "../types.js";
import { kbdbFetch } from "../lib/kbdb-client.js";
import { errorResponse, successResponse } from "../lib/cypher-client.js";

// 基本盤 entries row（與舊 v3 block 欄位 1:1，差別只在 type→entry_type）
interface KbdbBlock {
  id: string;
  page_name?: string | null;
  content?: string | null;
  entry_type?: string;
  tags_json?: string;
  metadata_json?: string | null;
  source?: string | null;
  updated_at?: number;
}

async function kbdbList(env: Env, entryType: string, limit = 100): Promise<KbdbBlock[]> {
  const resp = await kbdbFetch(env, `/entries?entry_type=${encodeURIComponent(entryType)}&limit=${limit}`);
  if (!resp.ok) throw new Error(`KBDB list entry_type=${entryType} HTTP ${resp.status}`);
  const data = await resp.json<{ entries?: KbdbBlock[] }>();
  return data.entries ?? [];
}

async function kbdbGetByPageName(env: Env, pageName: string): Promise<KbdbBlock | null> {
  const resp = await kbdbFetch(env, `/entries?page_name=${encodeURIComponent(pageName)}&limit=1`);
  if (!resp.ok) return null;
  const data = await resp.json<{ entries?: KbdbBlock[] }>();
  return data.entries?.[0] ?? null;
}

function parseTags(tagsJson?: string): string[] {
  if (!tagsJson) return [];
  try {
    const arr = JSON.parse(tagsJson);
    return Array.isArray(arr) ? arr : [];
  } catch {
    return [];
  }
}

export function registerListSkills(server: McpServer, env: Env) {
  server.tool(
    toolName("list_skills"),
    "列所有 agent-skill blocks（從 arcrun/registry/skills/ 同步進 KBDB）。每個 skill 是個 markdown playbook，描述 AI 面對 X 問題該怎麼想 + 該用哪個 example。回 [{slug, title, tags}]。call get_skill(slug) 拿完整內文。",
    {
      tag: z.string().optional().describe("optional 標籤過濾。如 'rag' / 'watcher' / 'debug'"),
    },
    async ({ tag }) => {
      try {
        const blocks = await kbdbList(env, "agent-skill", 100);
        const skills = blocks
          .map((b) => {
            const tags = parseTags(b.tags_json);
            let title = b.page_name?.replace(/^skill-/, "") ?? "(no title)";
            try {
              const meta = b.metadata_json ? JSON.parse(b.metadata_json) : null;
              if (meta?.title) title = meta.title;
            } catch {}
            return {
              slug: b.page_name?.replace(/^skill-/, "") ?? "",
              page_name: b.page_name,
              title,
              tags,
              chars: (b.content ?? "").length,
            };
          })
          .filter((s) => !tag || s.tags.includes(`skill:${tag}`) || s.tags.includes(tag) || s.slug.includes(tag));

        return successResponse(
          { count: skills.length, skills },
          [
            skills.length === 0
              ? "沒有 skill 命中。試 list_skills() 不帶 tag 看全部"
              : "call arcrun_get_skill(slug) 拿單個 skill 完整 markdown",
          ],
        );
      } catch (e) {
        return errorResponse(
          "fetch_failed",
          e instanceof Error ? e.message : String(e),
          ["稍後重試", "若持續失敗，告訴 leo"],
        );
      }
    },
  );
}

export function registerGetSkill(server: McpServer, env: Env) {
  server.tool(
    toolName("get_skill"),
    "拿單一 agent-skill 完整 markdown playbook。slug 從 list_skills 取得。",
    {
      slug: z.string().describe("skill slug，例如 'build_watcher_workflow' / 'rag_with_arcrun'"),
    },
    async ({ slug }) => {
      try {
        const pageName = slug.startsWith("skill-") ? slug : `skill-${slug}`;
        const block = await kbdbGetByPageName(env, pageName);
        if (!block) {
          return errorResponse(
            "not_found",
            `skill "${slug}" 不存在`,
            [
              "call arcrun_list_skills() 看可用 slug",
              "確認拼字正確（不需要 'skill-' prefix）",
            ],
          );
        }
        return successResponse({
          slug,
          page_name: block.page_name,
          content: block.content,
          tags: parseTags(block.tags_json),
        });
      } catch (e) {
        return errorResponse(
          "fetch_failed",
          e instanceof Error ? e.message : String(e),
          ["稍後重試"],
        );
      }
    },
  );
}

export function registerListExamples(server: McpServer, env: Env) {
  server.tool(
    toolName("list_examples"),
    "列所有 workflow-example blocks（從 arcrun/registry/examples/ 同步進 KBDB）。每個 example 是可直接 push 的 workflow YAML 範本 + description。回 [{slug, tags}]。call get_example / search_examples 拿細節。",
    {
      tag: z.string().optional().describe("optional 標籤過濾。如 'rag' / 'cron' / 'llm' / 'webhook'"),
    },
    async ({ tag }) => {
      try {
        const blocks = await kbdbList(env, "workflow-example", 200);
        const examples = blocks
          .map((b) => {
            const tags = parseTags(b.tags_json);
            return {
              slug: b.page_name?.replace(/^example-/, "") ?? "",
              page_name: b.page_name,
              tags,
              chars: (b.content ?? "").length,
            };
          })
          .filter((e) => !tag || e.tags.includes(tag) || e.tags.includes(`example:${tag}`) || e.slug.includes(tag));

        return successResponse(
          { count: examples.length, examples },
          [
            examples.length === 0
              ? "沒有 example 命中。試 list_examples() 不帶 tag 看全部"
              : "call arcrun_get_example(slug) 拿單個 YAML + description",
          ],
        );
      } catch (e) {
        return errorResponse(
          "fetch_failed",
          e instanceof Error ? e.message : String(e),
          ["稍後重試"],
        );
      }
    },
  );
}

export function registerGetExample(server: McpServer, env: Env) {
  server.tool(
    toolName("get_example"),
    "拿單一 workflow-example 完整 YAML + description。slug 從 list_examples / search_examples 取得。可直接拿 YAML 改成你自己的 → push。",
    {
      slug: z.string().describe("example slug，例如 'rag-search-answer' / 'cron-watcher'"),
    },
    async ({ slug }) => {
      try {
        const pageName = slug.startsWith("example-") ? slug : `example-${slug}`;
        const block = await kbdbGetByPageName(env, pageName);
        if (!block) {
          return errorResponse(
            "not_found",
            `example "${slug}" 不存在`,
            [
              "call arcrun_list_examples() 看可用 slug",
              "或 arcrun_search_examples(use_case) 用自然語言找",
            ],
          );
        }

        let description_md = "";
        try {
          const meta = block.metadata_json ? JSON.parse(block.metadata_json) : null;
          description_md = meta?.description_md ?? "";
        } catch {}

        return successResponse({
          slug,
          page_name: block.page_name,
          workflow_yaml: block.content,
          description_md,
          tags: parseTags(block.tags_json),
        }, [
          "拿 workflow_yaml 改成你自己的 → call arcrun_push_workflow",
          "看 description_md 了解設計意圖 / 改造方向",
        ]);
      } catch (e) {
        return errorResponse(
          "fetch_failed",
          e instanceof Error ? e.message : String(e),
          ["稍後重試"],
        );
      }
    },
  );
}

export function registerSearchExamples(server: McpServer, env: Env) {
  server.tool(
    toolName("search_examples"),
    "用 use case 關鍵字搜 workflow examples，回最相關 N 個。" +
      "注意：基本盤目前是 D1 LIKE 關鍵字搜尋（非語義 embedding；語義是 kbdb-base Phase 1 的 embed 模組，尚未上）。" +
      "→ 用具體詞（'email'、'cron'、'rag'）比整句自然語言命中率高。也會比對 slug/tag。",
    {
      query: z.string().min(2).describe("use case 關鍵字，例如 'email 摘要' / 'cron 排程' / 'rag'。基本盤是關鍵字非語義，用詞要具體"),
      top_k: z.number().int().min(1).max(20).optional().describe("回幾個結果（預設 5）"),
    },
    async ({ query, top_k }) => {
      try {
        const k = top_k ?? 5;
        const q = query.trim();

        // 基本盤無語義 search：撈全部 workflow-example，用 query 對 content/slug/tag 做關鍵字比對排序。
        // （examples 只有 ~10 筆，client 端過濾零負擔；embed 模組上線後可改打語義 search）
        const blocks = await kbdbList(env, "workflow-example", 200);
        const ql = q.toLowerCase();
        const terms = ql.split(/\s+/).filter(Boolean);

        const scored = blocks
          .map((b) => {
            const slug = b.page_name?.replace(/^example-/, "") ?? "";
            const tags = parseTags(b.tags_json);
            const hay = `${slug} ${tags.join(" ")} ${(b.content ?? "")}`.toLowerCase();
            // 每個 term 命中 +1；slug/tag 命中額外加權
            let score = 0;
            for (const t of terms) {
              if (hay.includes(t)) score += 1;
              if (slug.toLowerCase().includes(t)) score += 2;
              if (tags.some((tag) => tag.toLowerCase().includes(t))) score += 2;
            }
            return { b, slug, tags, score };
          })
          .filter((r) => r.score > 0)
          .sort((a, b) => b.score - a.score)
          .slice(0, k);

        const examples = scored.map((r) => ({
          slug: r.slug,
          page_name: r.b.page_name,
          score: r.score,
          tags: r.tags,
          preview: (r.b.content ?? "").slice(0, 200),
        }));

        if (examples.length === 0) {
          return successResponse(
            { count: 0, examples: [], query: q },
            [
              "關鍵字沒命中（基本盤是 LIKE 非語義，換更具體/不同的詞再試）",
              "改用 arcrun_list_examples(tag='...') 走 tag 過濾",
              "或 arcrun_list_examples() 看全部清單自己挑",
            ],
          );
        }

        return successResponse(
          { count: examples.length, examples, query: q, search_mode: "keyword" },
          [
            "call arcrun_get_example(slug) 拿完整 YAML",
            "score 高 = 關鍵字命中越多（slug/tag 命中加權）",
            "search_mode:keyword — 基本盤無語義，命中靠字面；換具體詞可改善",
          ],
        );
      } catch (e) {
        return errorResponse(
          "internal_error",
          e instanceof Error ? e.message : String(e),
          ["重試一次"],
        );
      }
    },
  );
}

export function registerAllSkillExampleTools(server: McpServer, env: Env) {
  registerListSkills(server, env);
  registerGetSkill(server, env);
  registerListExamples(server, env);
  registerGetExample(server, env);
  registerSearchExamples(server, env);
}
