///|
pub(all) enum SkillAssetKind {
  MarketDiagnosisSkill
  StrategyRoutingSkill
  TradeDecisionSkill
  StrategyNote
  RiskControlNote
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SkillAsset {
  id : String
  book_path : String
  title : String
  kind : SkillAssetKind
  summary : String
  pattern_tags : Array[@domain.PatternTag]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SkillCatalog {
  assets : Array[SkillAsset]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn skill_asset(
  id : String,
  book_path : String,
  title : String,
  kind : SkillAssetKind,
  summary : String,
  pattern_tags? : Array[@domain.PatternTag] = [],
) -> SkillAsset {
  { id, book_path, title, kind, summary, pattern_tags }
}

///|
fn push_unique_asset(items : Array[SkillAsset], asset : SkillAsset) -> Unit {
  if !items.any(fn(existing) { existing.id == asset.id }) {
    items.push(asset)
  }
}

///|
pub fn stage1_skill_assets() -> Array[SkillAsset] {
  [
    skill_asset(
      "skill.market-diagnosis.core",
      "skills/market-diagnosis/core.md",
      "Market diagnosis frame",
      MarketDiagnosisSkill,
      "classify cycle position, direction, phase, confidence, and pattern tags from bounded evidence",
    ),
    skill_asset(
      "skill.market-diagnosis.bar-by-bar",
      "skills/market-diagnosis/bar-by-bar-checklist.md",
      "Bar-by-bar checklist",
      MarketDiagnosisSkill,
      "force closed-bar evidence, signal-bar quality, follow-through, and location checks",
    ),
    skill_asset(
      "skill.strategy-routing.pattern-tags",
      "skills/strategy-routing/pattern-tags.md",
      "Pattern tag routing guide",
      StrategyRoutingSkill,
      "explain which detected pattern tags route to which trade-decision notes",
    ),
  ]
}

///|
pub fn stage2_base_skill_assets() -> Array[SkillAsset] {
  [
    skill_asset(
      "skill.trade-decision.core",
      "skills/trade-decision/core.md",
      "Trade decision frame",
      TradeDecisionSkill,
      "choose no-order, wait, limit, breakout, or market action from routed evidence",
    ),
    skill_asset(
      "strategy.risk-control",
      "wiki/strategy-notes/risk-control.md",
      "Risk, stop, target, and sizing",
      RiskControlNote,
      "reject weak equation, missing location, or poor risk/reward before any order-shaped output",
    ),
    skill_asset(
      "strategy.measured-move",
      "wiki/strategy-notes/measured-move.md",
      "Measured move and structure targets",
      StrategyNote,
      "use prior legs, ranges, and magnets as target context",
      pattern_tags=[MeasuredMove],
    ),
  ]
}

///|
pub fn strategy_assets_for_pattern(
  pattern : @domain.PatternTag,
) -> Array[SkillAsset] {
  match pattern {
    Wedge =>
      [
        skill_asset(
          "strategy.wedge",
          "wiki/strategy-notes/wedge.md",
          "Wedge and three-push structures",
          StrategyNote,
          "handle wedge pullbacks, wedge reversals, and three-push exhaustion",
          pattern_tags=[Wedge],
        ),
      ]
    ReversalAttempt =>
      [
        skill_asset(
          "strategy.second-entry",
          "wiki/strategy-notes/second-entry.md",
          "Second-entry confirmation",
          StrategyNote,
          "prefer second entries after first reversal attempts fail or retest",
          pattern_tags=[ReversalAttempt],
        ),
      ]
    MajorTrendReversal =>
      [
        skill_asset(
          "strategy.second-entry",
          "wiki/strategy-notes/second-entry.md",
          "Second-entry confirmation",
          StrategyNote,
          "prefer second entries after first reversal attempts fail or retest",
          pattern_tags=[ReversalAttempt],
        ),
        skill_asset(
          "strategy.major-trend-reversal",
          "wiki/strategy-notes/major-trend-reversal.md",
          "Major trend reversal",
          StrategyNote,
          "require trend break, pullback, retest, and credible reversal evidence",
          pattern_tags=[MajorTrendReversal],
        ),
      ]
    FinalFlag =>
      [
        skill_asset(
          "strategy.second-entry",
          "wiki/strategy-notes/second-entry.md",
          "Second-entry confirmation",
          StrategyNote,
          "prefer second entries after first reversal attempts fail or retest",
          pattern_tags=[ReversalAttempt],
        ),
        skill_asset(
          "strategy.final-flag",
          "wiki/strategy-notes/final-flag.md",
          "Final flag and trend-end behavior",
          StrategyNote,
          "treat final flags as late-trend structures needing confirmation",
          pattern_tags=[FinalFlag],
        ),
      ]
    H1 | H2 | L1 | L2 =>
      [
        skill_asset(
          "strategy.hl-count",
          "wiki/strategy-notes/hl-count.md",
          "H1/H2/L1/L2 count entries",
          StrategyNote,
          "count first and second pullback entries without confusing EMA gap counts",
          pattern_tags=[H1, H2, L1, L2],
        ),
      ]
    BreakoutTest | BreakoutPullback =>
      [
        skill_asset(
          "strategy.breakout-test",
          "wiki/strategy-notes/breakout-test.md",
          "Breakout tests and pullbacks",
          StrategyNote,
          "separate breakout tests, pullbacks, and failed-failure continuation setups",
          pattern_tags=[BreakoutTest, BreakoutPullback],
        ),
      ]
    BreakoutFailure =>
      [
        skill_asset(
          "strategy.breakout-test",
          "wiki/strategy-notes/breakout-test.md",
          "Breakout tests and pullbacks",
          StrategyNote,
          "separate breakout tests, pullbacks, and failed-failure continuation setups",
          pattern_tags=[BreakoutTest, BreakoutPullback],
        ),
        skill_asset(
          "strategy.failed-signal-magnet",
          "wiki/strategy-notes/failed-signal-magnet.md",
          "Failed signals and magnets",
          StrategyNote,
          "track trapped traders and likely magnetic prices after signal failure",
          pattern_tags=[BreakoutFailure, FailedSignal],
        ),
      ]
    AlwaysIn =>
      [
        skill_asset(
          "strategy.always-in",
          "wiki/strategy-notes/always-in.md",
          "Always-in and 20-gap-bar context",
          StrategyNote,
          "treat strong always-in contexts as requiring clear evidence before fading",
          pattern_tags=[AlwaysIn],
        ),
      ]
    Barbwire | Overlap | MiddleRange =>
      [
        skill_asset(
          "strategy.no-trade-overlap",
          "wiki/strategy-notes/no-trade-overlap.md",
          "Barbwire, overlap, and range-middle no-trade",
          StrategyNote,
          "default to no-order or wait in overlap-heavy range-middle conditions",
          pattern_tags=[Barbwire, Overlap, MiddleRange],
        ),
      ]
    FailedSignal =>
      [
        skill_asset(
          "strategy.failed-signal-magnet",
          "wiki/strategy-notes/failed-signal-magnet.md",
          "Failed signals and magnets",
          StrategyNote,
          "track trapped traders and likely magnetic prices after signal failure",
          pattern_tags=[BreakoutFailure, FailedSignal],
        ),
      ]
    Triangle =>
      [
        skill_asset(
          "strategy.triangle",
          "wiki/strategy-notes/triangle.md",
          "Triangle and converging structures",
          StrategyNote,
          "avoid forcing direction inside compression until breakout context is clear",
          pattern_tags=[Triangle],
        ),
      ]
    DoubleTopBottom =>
      [
        skill_asset(
          "strategy.double-top-bottom",
          "wiki/strategy-notes/double-top-bottom.md",
          "Double tops, double bottoms, and micro structures",
          StrategyNote,
          "use retests and micro double structures as location evidence, not standalone orders",
          pattern_tags=[DoubleTopBottom],
        ),
      ]
    MeasuredMove =>
      [
        skill_asset(
          "strategy.measured-move",
          "wiki/strategy-notes/measured-move.md",
          "Measured move and structure targets",
          StrategyNote,
          "use prior legs, ranges, and magnets as target context",
          pattern_tags=[MeasuredMove],
        ),
      ]
    UnknownPattern(_) => []
  }
}

///|
pub fn route_strategy_assets(
  diagnosis : @domain.Stage1Diagnosis,
) -> Array[SkillAsset] {
  let assets : Array[SkillAsset] = []
  for asset in stage2_base_skill_assets() {
    push_unique_asset(assets, asset)
  }
  for pattern in diagnosis.patterns {
    for asset in strategy_assets_for_pattern(pattern) {
      push_unique_asset(assets, asset)
    }
  }
  assets
}

///|
pub fn route_strategy_skill_paths(
  diagnosis : @domain.Stage1Diagnosis,
) -> Array[@domain.StrategyFile] {
  route_strategy_assets(diagnosis).map(fn(asset) { asset.book_path })
}

///|
pub fn price_action_skill_catalog() -> SkillCatalog {
  let assets : Array[SkillAsset] = []
  for asset in stage1_skill_assets() {
    push_unique_asset(assets, asset)
  }
  let fixture = @domain.stage1_diagnosis(UnknownCycle, Neutral, 0, Stable, [
    Wedge,
    ReversalAttempt,
    MajorTrendReversal,
    FinalFlag,
    H1,
    BreakoutTest,
    BreakoutPullback,
    BreakoutFailure,
    AlwaysIn,
    Barbwire,
    FailedSignal,
    Triangle,
    DoubleTopBottom,
    MeasuredMove,
  ])
  for asset in route_strategy_assets(fixture) {
    push_unique_asset(assets, asset)
  }
  { assets, }
}