///|
pub(all) enum SkillMigrationDisposition {
  ImportedAsSkill
  ImportedAsStrategyNote
  ImportedAsReference
  NeedsAuthorReview
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SkillMigrationInput {
  source_root : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SkillSourceRef {
  source_path : String
  target_asset_id : String?
  target_book_path : String
  disposition : SkillMigrationDisposition
  note : String
  pattern_tags : Array[@domain.PatternTag]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SkillMigrationPlan {
  source_root : String
  catalog : SkillCatalog
  source_count : Int
  mapped_count : Int
  reference_count : Int
  review_count : Int
  sources : Array[SkillSourceRef]
  summary : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn skill_migration_input(
  source_root? : String = "../paa/prompt_engineering",
) -> SkillMigrationInput {
  { source_root, }
}

///|
pub fn skill_source_ref(
  source_path : String,
  target_book_path : String,
  disposition : SkillMigrationDisposition,
  note : String,
  target_asset_id? : String,
  pattern_tags? : Array[@domain.PatternTag] = [],
) -> SkillSourceRef {
  {
    source_path,
    target_asset_id,
    target_book_path,
    disposition,
    note,
    pattern_tags,
  }
}

///|
fn source_path(input : SkillMigrationInput, relative_path : String) -> String {
  "\{input.source_root}/\{relative_path}"
}

///|
fn skill_source(
  input : SkillMigrationInput,
  relative_path : String,
  target_asset_id : String,
  target_book_path : String,
  note : String,
) -> SkillSourceRef {
  skill_source_ref(
    source_path(input, relative_path),
    target_book_path,
    ImportedAsSkill,
    note,
    target_asset_id~,
  )
}

///|
fn strategy_source(
  input : SkillMigrationInput,
  relative_path : String,
  target_asset_id : String,
  target_book_path : String,
  note : String,
  pattern_tags? : Array[@domain.PatternTag] = [],
) -> SkillSourceRef {
  skill_source_ref(
    source_path(input, relative_path),
    target_book_path,
    ImportedAsStrategyNote,
    note,
    target_asset_id~,
    pattern_tags~,
  )
}

///|
fn reference_source(
  input : SkillMigrationInput,
  relative_path : String,
  target_book_path : String,
  note : String,
) -> SkillSourceRef {
  skill_source_ref(
    source_path(input, relative_path),
    target_book_path,
    ImportedAsReference,
    note,
  )
}

///|
fn prompt_sources(input : SkillMigrationInput) -> Array[SkillSourceRef] {
  [
    skill_source(
      input, "市场诊断框架.txt", "skill.market-diagnosis.core", "skills/market-diagnosis/core.md",
      "core Stage 1 market diagnosis frame",
    ),
    skill_source(
      input, "逐棒分析检查单.txt", "skill.market-diagnosis.bar-by-bar", "skills/market-diagnosis/bar-by-bar-checklist.md",
      "closed-bar and signal-quality checklist",
    ),
    skill_source(
      input, "二元决策.txt", "skill.trade-decision.core", "skills/trade-decision/core.md",
      "core Stage 2 decision frame",
    ),
    reference_source(
      input, "提示词大纲_人设与思维方式.txt", "wiki/concepts/operator-persona-and-reasoning.md",
      "operator persona and reasoning style reference",
    ),
    strategy_source(
      input, "文件17-止损和止盈与仓位管理.txt", "strategy.risk-control",
      "wiki/strategy-notes/risk-control.md", "risk, stop, target, and sizing constraints",
    ),
    strategy_source(
      input,
      "文件23-MeasuredMove与结构目标.txt",
      "strategy.measured-move",
      "wiki/strategy-notes/measured-move.md",
      "measured-move and magnet target context",
      pattern_tags=[MeasuredMove],
    ),
    strategy_source(
      input,
      "文件20-AlwaysIn与20GB.txt",
      "strategy.always-in",
      "wiki/strategy-notes/always-in.md",
      "always-in and 20-gap-bar context",
      pattern_tags=[AlwaysIn],
    ),
    strategy_source(
      input,
      "文件14-楔形形态分析交易.txt",
      "strategy.wedge",
      "wiki/strategy-notes/wedge.md",
      "wedge, three-push, and exhaustion behavior",
      pattern_tags=[Wedge],
    ),
    strategy_source(
      input,
      "文件15-二次入场机会.txt",
      "strategy.second-entry",
      "wiki/strategy-notes/second-entry.md",
      "second-entry confirmation after failed first attempts",
      pattern_tags=[ReversalAttempt],
    ),
    strategy_source(
      input,
      "文件25-主要趋势反转MTR.txt",
      "strategy.major-trend-reversal",
      "wiki/strategy-notes/major-trend-reversal.md",
      "major trend reversal checklist",
      pattern_tags=[MajorTrendReversal],
    ),
    strategy_source(
      input,
      "文件24-最终旗形与趋势末端.txt",
      "strategy.final-flag",
      "wiki/strategy-notes/final-flag.md",
      "final flag and trend-end behavior",
      pattern_tags=[FinalFlag],
    ),
    strategy_source(
      input,
      "文件19-H1H2-L1L2计数.txt",
      "strategy.hl-count",
      "wiki/strategy-notes/hl-count.md",
      "H1/H2/L1/L2 pullback counting",
      pattern_tags=[H1, H2, L1, L2],
    ),
    strategy_source(
      input,
      "文件18-突破失败与突破测试.txt",
      "strategy.breakout-test",
      "wiki/strategy-notes/breakout-test.md",
      "breakout tests, pullbacks, and failed breakouts",
      pattern_tags=[BreakoutTest, BreakoutPullback, BreakoutFailure],
    ),
    strategy_source(
      input,
      "文件22-信号失败后的磁力位.txt",
      "strategy.failed-signal-magnet",
      "wiki/strategy-notes/failed-signal-magnet.md",
      "failed signals, trapped traders, and magnet prices",
      pattern_tags=[FailedSignal, BreakoutFailure],
    ),
    strategy_source(
      input,
      "文件21-铁丝网与无交易环境.txt",
      "strategy.no-trade-overlap",
      "wiki/strategy-notes/no-trade-overlap.md",
      "barbwire, overlap, and range-middle no-trade filters",
      pattern_tags=[Barbwire, Overlap, MiddleRange],
    ),
    strategy_source(
      input,
      "文件27-三角形与收敛形态.txt",
      "strategy.triangle",
      "wiki/strategy-notes/triangle.md",
      "triangle and converging-structure handling",
      pattern_tags=[Triangle],
    ),
    strategy_source(
      input,
      "文件28-双重顶底与微型结构.txt",
      "strategy.double-top-bottom",
      "wiki/strategy-notes/double-top-bottom.md",
      "double tops, double bottoms, and micro structures",
      pattern_tags=[DoubleTopBottom],
    ),
    strategy_source(
      input, "文件13-窄通道与宽通道策略.txt", "strategy.channel-context",
      "wiki/strategy-notes/channel-context.md", "narrow-channel and broad-channel context note",
    ),
    strategy_source(
      input, "上涨通道分析识别.txt", "strategy.bull-channel-context", "wiki/strategy-notes/bull-channel-context.md",
      "bull-channel diagnosis reference",
    ),
    strategy_source(
      input, "上涨通道交易策略.txt", "strategy.bull-channel-context", "wiki/strategy-notes/bull-channel-context.md",
      "bull-channel trade-decision reference",
    ),
    strategy_source(
      input, "下跌通道分析识别.txt", "strategy.bear-channel-context", "wiki/strategy-notes/bear-channel-context.md",
      "bear-channel diagnosis reference",
    ),
    strategy_source(
      input, "下跌通道交易策略.txt", "strategy.bear-channel-context", "wiki/strategy-notes/bear-channel-context.md",
      "bear-channel trade-decision reference",
    ),
    strategy_source(
      input, "极速上涨分析识别.txt", "strategy.bull-spike-context", "wiki/strategy-notes/bull-spike-context.md",
      "bull spike diagnosis reference",
    ),
    strategy_source(
      input, "极速上涨交易策略.txt", "strategy.bull-spike-context", "wiki/strategy-notes/bull-spike-context.md",
      "bull spike trade-decision reference",
    ),
    strategy_source(
      input, "极速下跌分析识别.txt", "strategy.bear-spike-context", "wiki/strategy-notes/bear-spike-context.md",
      "bear spike diagnosis reference",
    ),
    strategy_source(
      input, "极速下跌交易策略.txt", "strategy.bear-spike-context", "wiki/strategy-notes/bear-spike-context.md",
      "bear spike trade-decision reference",
    ),
    strategy_source(
      input, "震荡区间分析识别.txt", "strategy.trading-range-context", "wiki/strategy-notes/trading-range-context.md",
      "trading-range diagnosis reference",
    ),
    strategy_source(
      input, "震荡区间交易策略.txt", "strategy.trading-range-context", "wiki/strategy-notes/trading-range-context.md",
      "trading-range trade-decision reference",
    ),
    strategy_source(
      input, "文件16-K线信号识别.txt", "strategy.signal-bar-quality", "wiki/strategy-notes/signal-bar-quality.md",
      "signal-bar and candle-quality reference",
    ),
    reference_source(
      input, "_reference/abbrev_glossary.md", "wiki/concepts/abbrev-glossary.md",
      "abbreviation glossary imported as concept reference",
    ),
    reference_source(
      input, "_reference/kb_concept_map.md", "wiki/concepts/kb-concept-map.md", "source knowledge-base concept map",
    ),
    reference_source(
      input, "_reference/pattern_enum.md", "wiki/concepts/pattern-enum.md", "source pattern enum reference for schema parity",
    ),
  ]
}

///|
fn count_disposition(
  sources : Array[SkillSourceRef],
  disposition : SkillMigrationDisposition,
) -> Int {
  sources.fold(init=0, fn(count, source) {
    if source.disposition == disposition {
      count + 1
    } else {
      count
    }
  })
}

///|
pub fn prepare_skill_migration_plan(
  input? : SkillMigrationInput = skill_migration_input(),
) -> SkillMigrationPlan {
  let sources = prompt_sources(input)
  let review_count = count_disposition(sources, NeedsAuthorReview)
  let reference_count = count_disposition(sources, ImportedAsReference)
  let mapped_count = sources.length() - review_count
  {
    source_root: input.source_root,
    catalog: price_action_skill_catalog(),
    source_count: sources.length(),
    mapped_count,
    reference_count,
    review_count,
    sources,
    summary: if review_count == 0 {
      "skill migration maps \{mapped_count}/\{sources.length()} PA prompt source(s) into MoonBook skill and wiki targets"
    } else {
      "skill migration has \{review_count} PA prompt source(s) needing author review"
    },
  }
}