/**
 * prompt_recipe Zod schema
 * SDD: matrix/arcrun/.agents/specs/recipe-system/design.md §2.1
 *
 * 平行於既有 auth_recipe / api_recipe，存 RECIPES KV (key: `prompt_recipe:{name}`)
 * 容器 + recipe 模式：claude_api 是容器，recipe 是配方
 */

import { z } from 'zod';

// ── Transform 白名單 ──────────────────────────────────────────────────────────
// 限制 transform 種類避免變 mini-DSL；超過範圍請寫零件
export const TRANSFORM_NAMES = [
  'json_array',           // array → JSON.stringify 整體
  'to_string',            // 任意值 → String(x)
  'join',                 // array → join(sep)，sep 預設換行
  'markdown_list',        // array → "- a\n- b\n- c"
  'extract_field',        // array of object → 抽 field 後的 array（再可串其他 transform）
  'first',                // array → first element（取單一）
  'pluck_content',        // KBDB blocks array → 抽 content 後 join 雙換行（草稿合併常用）
] as const;

/** transform 表示法：name 或 name:arg（如 extract_field:page_name） */
export const TransformSchema = z.string().regex(/^[a-z_]+(:.+)?$/, 'transform 必須為 name 或 name:arg 格式');

// ── Fragment：從 KBDB / KV 抓固定資料 ──────────────────────────────────────────
export const KBDBBlockFragmentSchema = z.object({
  var: z.string().min(1),               // prompt template 內的變數名
  source: z.literal('kbdb_block'),
  block_id: z.string().optional(),       // 二擇一
  block_page_name: z.string().optional(), // 比 block_id 穩定
  field: z.string().default('content'),   // 抓 block 的哪個欄位
});

export const KVFragmentSchema = z.object({
  var: z.string().min(1),
  source: z.literal('kv'),
  key: z.string().min(1),
});

// discriminatedUnion 對 refined zod object 不支援，故拆成驗證後 + 單獨檢查 block_id|page_name
export const FragmentSchema = z.discriminatedUnion('source', [
  KBDBBlockFragmentSchema,
  KVFragmentSchema,
]).superRefine((d, ctx) => {
  if (d.source === 'kbdb_block' && !d.block_id && !d.block_page_name) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: 'block_id 或 block_page_name 必填其一',
    });
  }
});

// ── Input：從 workflow context 取值（含 transform） ────────────────────────────
export const InputSchema = z.object({
  var: z.string().min(1),
  from: z.string().min(1),               // JSONPath-lite，如 "ctx.read_drafts.blocks"
  transform: TransformSchema.optional(),
  default: z.unknown().optional(),       // from 取不到時的預設值（避免炸 prompt）
});

// ── Prompt 組裝 ──────────────────────────────────────────────────────────────
export const PromptAssemblySchema = z.object({
  system: z.string().min(1),             // 模板，可含 {{var}}
  user: z.string().min(1),
});

// ── 輸出規格 ──────────────────────────────────────────────────────────────────
export const OutputSpecSchema = z.object({
  format: z.enum(['text', 'json']).default('text'),
  // 若 format=json，可選 schema 做 parse 後驗證（簡化版，列必填欄位即可）
  required_fields: z.array(z.string()).optional(),
});

// ── 完整 prompt_recipe 定義 ────────────────────────────────────────────────────
export const PromptRecipeSchema = z.object({
  kind: z.literal('prompt_recipe'),
  name: z.string().min(1).regex(/^[a-z][a-z0-9_]*$/, 'name 為 lowercase + underscore'),
  version: z.number().int().positive().default(1),
  description: z.string().optional(),
  model: z.enum(['haiku', 'sonnet', 'opus']).default('sonnet'),
  fragments: z.array(FragmentSchema).default([]),
  inputs: z.array(InputSchema).default([]),
  prompt_assembly: PromptAssemblySchema,
  output: OutputSpecSchema.default({ format: 'text' }),
});

export type PromptRecipe = z.infer<typeof PromptRecipeSchema>;
export type Fragment = z.infer<typeof FragmentSchema>;
export type RecipeInput = z.infer<typeof InputSchema>;
