import { z } from 'zod';

/**
 * SKILL.md frontmatter schema(Anthropic Skills 标准 + PAC 业务字段)。
 *
 * 设计:
 *   - name / description 是 Anthropic Skills 必填(name 唯一,description 是 LLM 自动 selector 的判断依据)
 *   - applies / priority / allowedPopulation 是 PAC 业务字段,用于声明式 matcher
 *   - body 不在 frontmatter,是 SKILL.md `---` 分隔线之后的整段 markdown,registry 单独存
 *
 * 各 applies 字段全可选,缺省即"不限"。**只有声明了的字段才参与 match**。
 */
export const SkillFrontmatterSchema = z.object({
  /** 全 callKey 唯一标识,kebab-case,如 'diagnosis-K08-edentulism' */
  name: z.string().min(3).regex(/^[a-z][a-z0-9-]+[a-z0-9]$/i, {
    message: 'name 必须 kebab-case 字母数字,如 diagnosis-K08-edentulism',
  }),

  /** 加载条件描述(>=40 字,带语义上下文)。给运维 / LLM auto-selector 看 */
  description: z.string().min(40),

  /** 装配顺序(数小先,数大后,后写覆盖前;空 = 50 默认) */
  priority: z.number().int().min(0).max(1000).default(50),

  /** 跨维度排除 — 列出兼容的 population key(空数组 = 不限) */
  allowedPopulation: z.array(z.enum(['child', 'teen', 'adult', 'elder'])).default([]),

  /** SemVer,改文件 bump(给 promptVersion composeHash 用) */
  version: z.string().default('0.1.0'),

  /** 声明式 matcher(全可选,声明即生效) */
  applies: z
    .object({
      /** plan.reasons[0].scenario 必须等于 */
      scenario: z.string().optional(),
      /** 至少 1 个 reason 的 diagnosisCode 以此 prefix 开头(如 'K08') */
      diagnosisCodePrefix: z.string().optional(),
      /** 年龄下限(含),patient.age >= ageMin */
      ageMin: z.number().int().optional(),
      /** 年龄上限(含),patient.age <= ageMax */
      ageMax: z.number().int().optional(),
      /** 客户关系 */
      relationship: z.enum(['new', 'returning']).optional(),
    })
    .default({}),
});

export type SkillFrontmatter = z.infer<typeof SkillFrontmatterSchema>;

/**
 * 解析后的 skill,registry 内的最终形态。
 * body = SKILL.md 分隔线之后的 markdown 正文。
 * sourcePath = 文件绝对路径,便于错误提示。
 */
export interface Skill {
  readonly frontmatter: SkillFrontmatter;
  readonly body: string;
  readonly sourcePath: string;
}

/**
 * Composer 派生的 match context,来自 input 而非 raw plan/patient。
 * 每个字段都可空 — 跟 SKILL.applies 的可选字段对称 match。
 */
export interface SkillMatchContext {
  scenario: string | null;
  diagnosisCodes: string[]; // 如 ['K08', 'K05'](已抽 prefix)
  age: number | null;
  /** child<14 / teen 14-17 / adult 18-64 / elder >=65 */
  population: 'child' | 'teen' | 'adult' | 'elder' | null;
  relationship: 'new' | 'returning';
}

export const POPULATION_THRESHOLDS = {
  CHILD_MAX: 13,
  TEEN_MIN: 14,
  TEEN_MAX: 17,
  ADULT_MIN: 18,
  ADULT_MAX: 64,
  ELDER_MIN: 65,
} as const;

export function classifyPopulation(
  age: number | null,
): SkillMatchContext['population'] {
  if (age === null) return null;
  if (age <= POPULATION_THRESHOLDS.CHILD_MAX) return 'child';
  if (age <= POPULATION_THRESHOLDS.TEEN_MAX) return 'teen';
  if (age <= POPULATION_THRESHOLDS.ADULT_MAX) return 'adult';
  return 'elder';
}
