/**
 * /init/seed 必須把種子的 3.12 三層欄位原樣寫進 KV —— SDD: workflow-discovery task 3.12/3.13
 *
 * 為什麼要有這個測試（別刪）：
 *   3.12 給 `RecipeDefinition` 加了 body_template / response_map / auth / binding_name，
 *   但 `/init/seed` 當時是**列舉欄位重建** recipe record ⇒ 不在名單上的欄位被靜默吃掉。
 *   症狀最惡劣的地方在於「哪裡都不會紅」：recipe 查得到、canonical_id 對、endpoint 對，
 *   只有跑起來像沒設定過（auth 掉了 ⇒ 走 HTTP 路徑去 fetch「@cf/…」這種不是網址的字串）。
 *   這與 2026-08-02 `syncManifest()` 列舉式重建吃掉 `manifest.daemon` 欄是同一型事故——
 *   當時的教訓寫著：「**東西還在不在**也要進機械閘」，本檔就是那道閘。
 *
 * 範圍：只驗「種子 → KV」這段（純資料搬運）。真的呼叫 Workers AI 由實例端到端驗。
 */
import { describe, it, expect } from 'vitest';
import { env, SELF } from 'cloudflare:test';
import { API_RECIPE_SEEDS } from '../src/lib/api-recipe-seeds';

type StoredRecipe = {
  canonical_id: string;
  endpoint: string;
  auth?: string;
  binding_name?: string;
  body_template?: Record<string, unknown>;
  response_map?: { text_path?: string; answer_marker?: string; strip_prefixes?: string[] };
};

async function seedThenRead(canonicalId: string): Promise<StoredRecipe> {
  const res = await SELF.fetch('https://example.com/init/seed', { method: 'POST' });
  // 測試環境沒有 KBDB binding ⇒ portal template 那段必然失敗、整體回 207（誠實回報，非本測目標）。
  // 本檔只管 API recipe 那半，所以驗它自己的計數，不驗整體 status。
  const body = await res.json<{ api_recipes: { seeded: number; failed: number; errors: string[] } }>();
  expect(body.api_recipes.errors).toEqual([]);
  expect(body.api_recipes.failed).toBe(0);
  const uuid = await env.RECIPES.get(`idx:installed:${canonicalId}`);
  expect(uuid, `${canonicalId} 沒有被 seed 進 KV`).toBeTruthy();
  return JSON.parse((await env.RECIPES.get(`recipe:${uuid}`))!) as StoredRecipe;
}

describe('/init/seed 不得靜默吃掉 recipe 的 3.12 欄位', () => {
  it('workers_ai_chat 種子本身宣告齊四個欄位（種子端）', () => {
    const seed = API_RECIPE_SEEDS.find(s => s.canonical_id === 'workers_ai_chat');
    expect(seed, 'workers_ai_chat 種子不存在＝裝完不會有免金鑰問答').toBeDefined();
    expect(seed!.auth).toBe('binding');
    expect(seed!.binding_name).toBe('AI');
    expect(seed!.endpoint.startsWith('@cf/'), 'binding 型的 endpoint＝模型 id').toBe(true);
    expect(seed!.body_template).toBeDefined();
    expect(seed!.response_map?.text_path).toBe('response');
  });

  it('seed 之後 KV 裡讀回來的仍帶 auth/binding_name/body_template/response_map（KV 端）', async () => {
    const stored = await seedThenRead('workers_ai_chat');
    expect(stored.auth, 'auth 掉了 ⇒ 會被當成 HTTP recipe 去 fetch 一個不是網址的字串').toBe('binding');
    expect(stored.binding_name).toBe('AI');
    expect(stored.body_template, 'body_template 掉了 ⇒ 整包 ctx 被當 payload 送給模型').toBeDefined();
    expect(stored.response_map?.text_path, 'response_map 掉了 ⇒ 下游拿不到 text').toBe('response');
    expect(stored.response_map?.answer_marker).toBe('【答】');
  });

  it('既有 HTTP 種子不受影響：沒宣告新欄位就是 undefined，不憑空長出來', async () => {
    const stored = await seedThenRead('telegram_send');
    expect(stored.auth).toBeUndefined();
    expect(stored.binding_name).toBeUndefined();
    expect(stored.body_template).toBeUndefined();
    expect(stored.response_map).toBeUndefined();
    expect(stored.endpoint).toContain('api.telegram.org');
  });
});
