///|
pub(all) enum LegacySettingDisposition {
  Migrated
  NeedsReview
  IgnoredUiOnly
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct LegacySettingsRef {
  source_path : String
  provider_model : String
  provider_base_url : String
  provider_api_key_present : Bool
  data_source_label : String
  symbol : @domain.Symbol
  timeframe : @domain.Timeframe
  analysis_bar_count : Int
  retry_max : Int
  retry_max_semantic : Int
  retry_stage2 : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct MigratedSetting {
  source_path : String
  target_path : String
  disposition : LegacySettingDisposition
  message : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct SuiteSettingsPlan {
  source_path : String
  suite_status : @model.SuiteStatusRef
  market_request : @data.MarketSourceRequest
  retry_policy : @job.RetryPolicy
  provider_snapshot_path : String
  provider_secret_redacted : Bool
  settings : Array[MigratedSetting]
  review_count : Int
  summary : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn legacy_settings_ref(
  source_path : String,
  provider_model : String,
  provider_base_url : String,
  data_source_label : String,
  symbol : @domain.Symbol,
  timeframe : @domain.Timeframe,
  provider_api_key_present? : Bool = false,
  analysis_bar_count? : Int = 100,
  retry_max? : Int = 3,
  retry_max_semantic? : Int = 1,
  retry_stage2? : Bool = true,
) -> LegacySettingsRef {
  {
    source_path,
    provider_model,
    provider_base_url,
    provider_api_key_present,
    data_source_label,
    symbol,
    timeframe,
    analysis_bar_count,
    retry_max,
    retry_max_semantic,
    retry_stage2,
  }
}

///|
fn source_to_data_source(
  label : String,
) -> (@domain.DataSource, LegacySettingDisposition, String) {
  match label {
    "tradingview" => (TradingView, Migrated, "mapped to TradingView adapter")
    "mt5" => (Mt5, Migrated, "mapped to MT5 adapter")
    "yfinance" => (Yfinance, Migrated, "mapped to yfinance adapter")
    "akshare" => (AkShare, Migrated, "mapped to AkShare adapter")
    "fixture" => (Fixture, Migrated, "mapped to local fixture adapter")
    "eastmoney" =>
      (
        AkShare,
        NeedsReview,
        "eastmoney is not a standalone Moonfish adapter yet; review AkShare mapping",
      )
    "tushare" =>
      (
        AkShare,
        NeedsReview,
        "tushare token settings stay outside Moonfish core; review AkShare mapping",
      )
    _ => (Fixture, NeedsReview, "unknown data source; defaulted to fixture")
  }
}

///|
fn clamp_retry(value : Int, max : Int) -> Int {
  if value < 0 {
    0
  } else if value > max {
    max
  } else {
    value
  }
}

///|
fn normalized_limit(value : Int) -> Int {
  if value < 1 {
    1
  } else {
    value
  }
}

///|
fn migrated_setting(
  source_path : String,
  target_path : String,
  disposition : LegacySettingDisposition,
  message : String,
) -> MigratedSetting {
  { source_path, target_path, disposition, message }
}

///|
fn count_review(items : Array[MigratedSetting]) -> Int {
  items.fold(init=0, fn(count, item) {
    if item.disposition is NeedsReview {
      count + 1
    } else {
      count
    }
  })
}

///|
pub fn prepare_suite_settings_plan(
  legacy : LegacySettingsRef,
  status_path? : String = @model.moonsuite_suite_status_path(),
) -> SuiteSettingsPlan {
  let (data_source, data_disposition, data_message) = source_to_data_source(
    legacy.data_source_label,
  )
  let suite_status = @model.suite_status_ref(
    status_path,
    legacy.provider_base_url,
    legacy.provider_model,
    ready=legacy.provider_base_url != "" && legacy.provider_model != "",
  )
  let market_request = @data.market_source_request(
    data_source,
    legacy.symbol,
    legacy.timeframe,
    limit=normalized_limit(legacy.analysis_bar_count),
  )
  let retry_policy = @job.default_retry_policy(
    max_attempts=clamp_retry(legacy.retry_max, 5),
    semantic_max_attempts=clamp_retry(legacy.retry_max_semantic, 3),
    retry_stage2=legacy.retry_stage2,
  )
  let settings = [
    migrated_setting(
      "provider.model",
      "suite-status.defaultModel",
      if legacy.provider_model == "" {
        NeedsReview
      } else {
        Migrated
      },
      "model selection moves to MoonGate suite status",
    ),
    migrated_setting(
      "provider.base_url",
      "suite-status.openaiBaseUrl",
      if legacy.provider_base_url == "" {
        NeedsReview
      } else {
        Migrated
      },
      "provider URL moves to MoonGate OpenAI-compatible gateway",
    ),
    migrated_setting(
      "provider.api_key",
      "moongate-secret-store",
      Migrated,
      if legacy.provider_api_key_present {
        "API key is not copied into Moonfish records; MoonGate owns secret storage"
      } else {
        "no plaintext API key present in legacy settings"
      },
    ),
    migrated_setting(
      "general.last_data_source", "market-source-request.data_source", data_disposition,
      data_message,
    ),
    migrated_setting(
      "general.last_symbol",
      "market-source-request.symbol",
      if legacy.symbol == "" {
        NeedsReview
      } else {
        Migrated
      },
      "operator symbol becomes a typed market request field",
    ),
    migrated_setting(
      "general.last_timeframe",
      "market-source-request.timeframe",
      if legacy.timeframe == "" {
        NeedsReview
      } else {
        Migrated
      },
      "operator timeframe becomes a typed market request field",
    ),
    migrated_setting(
      "validation.retry_*",
      "retry-policy",
      Migrated,
      "validation retry settings become a bounded MoonClaw retry policy",
    ),
    migrated_setting(
      "general.decision_flow_*",
      "moondesk-app-settings",
      IgnoredUiOnly,
      "legacy PyQt playback and zoom settings stay outside Moonfish core",
    ),
  ]
  let review_count = count_review(settings)
  {
    source_path: legacy.source_path,
    suite_status,
    market_request,
    retry_policy,
    provider_snapshot_path: "records/settings/provider-snapshot.json",
    provider_secret_redacted: true,
    settings,
    review_count,
    summary: if review_count == 0 {
      "suite settings migration ready for \{legacy.symbol} \{legacy.timeframe}"
    } else {
      "suite settings migration has \{review_count} item(s) needing review"
    },
  }
}