/**
 * scenario-helpers — framework-agnostic mapping helpers for the ПТИЦА dark
 * «Сценарии» tab. Shares the deficit semantics + RU formatting used by the light
 * Section 6 blocks (single source of truth = forecast-helpers), re-expressed here
 * with dark-cockpit "tone" classes (good/warn/bad) instead of light BadgeVariant.
 *
 * Deficit semantics (HARD): >0 недонасыщенность (повод строить),
 * <0 затоварка, ≈0 баланс. Mirrors forecast-helpers.deficitWord.
 */

import type {
  DemandSupplyForecast,
  ReportScenarios,
  ScenarioKey,
  ScenariosSummary,
} from "@/types/forecast";

/** Below this |deficit_index| the market reads as balanced (neutral tone). */
export const DEFICIT_BALANCE_EPS = 0.05;

/** Dark cockpit severity tone — drives the accent colour via CSS classes. */
export type Tone = "good" | "warn" | "bad" | "neutral";

/** deficit_index → tone (>0 good / <0 bad / ≈0 neutral). */
export function deficitTone(deficitIndex: number): Tone {
  if (deficitIndex > DEFICIT_BALANCE_EPS) return "good";
  if (deficitIndex < -DEFICIT_BALANCE_EPS) return "bad";
  return "neutral";
}

/** deficit_index → RU word (недонасыщенность / затоварка / баланс). */
export function deficitWord(deficitIndex: number): string {
  if (deficitIndex > DEFICIT_BALANCE_EPS) return "недонасыщенность";
  if (deficitIndex < -DEFICIT_BALANCE_EPS) return "затоварка";
  return "баланс";
}

/** Short verdict for the compare table «Вывод» column. */
export function deficitVerdict(deficitIndex: number): string {
  if (deficitIndex > 0.25) return "Сильный дефицит — премия к цене";
  if (deficitIndex > DEFICIT_BALANCE_EPS)
    return "Недонасыщенность — окно для выхода";
  if (deficitIndex < -DEFICIT_BALANCE_EPS) return "Затоварка — сдерживать темп";
  return "Баланс — контроль темпа продаж";
}

// ── Confidence ──────────────────────────────────────────────────────────────

import type { ConfidenceLevel } from "@/types/forecast";

export const CONFIDENCE_RU: Record<ConfidenceLevel, string> = {
  high: "высокая",
  medium: "средняя",
  low: "низкая",
};

/** ConfidenceLevel → conf-pill modifier class key (high/medium/low). */
export function confidencePill(
  level: ConfidenceLevel,
): "high" | "medium" | "low" {
  return level;
}

// ── Number formatting (ru typography) ─────────────────────────────────────────

/**
 * Fixed-decimal RU number. Normalises the leading ASCII minus to the Unicode
 * «−» (U+2212) per ui-microcopy. `.replace` hits only the leading sign (RU
 * grouping uses NBSP, not "-"), so the numeric part is untouched.
 */
export function fmtNum(value: number, digits = 1): string {
  return value
    .toLocaleString("ru", {
      minimumFractionDigits: digits,
      maximumFractionDigits: digits,
    })
    .replace("-", "−");
}

/** Signed deficit_index, e.g. «+0.18» / «−1.00» (Unicode minus). */
export function fmtSignedDeficit(deficitIndex: number, digits = 2): string {
  const body = fmtNum(deficitIndex, digits);
  return deficitIndex > 0 ? `+${body}` : body;
}

/** Round to integer with RU thousands grouping (квартиры). */
export function fmtInt(value: number): string {
  return Math.round(value).toLocaleString("ru-RU");
}

// ── Scenario selection ────────────────────────────────────────────────────────

/** Display order: base → aggressive → conservative (own → best → worst). */
export const SCENARIO_ORDER: ScenarioKey[] = [
  "base",
  "aggressive",
  "conservative",
];

export const SCENARIO_RU: Record<ScenarioKey, string> = {
  base: "Базовый сценарий",
  aggressive: "Агрессивный",
  conservative: "Консервативный",
};

export const SCENARIO_HINT: Record<ScenarioKey, string> = {
  base: "ставка без изменений",
  aggressive: "ставка ниже",
  conservative: "ставка выше",
};

/** Border-top accent class key per scenario (base blue / aggr green / cons yellow). */
export const SCENARIO_ACCENT: Record<ScenarioKey, "base" | "aggr" | "cons"> = {
  base: "base",
  aggressive: "aggr",
  conservative: "cons",
};

/**
 * Pick the forecast row at the target horizon, falling back to the longest
 * available horizon (mirrors ScenariosBlock.pickHorizonForecast).
 */
export function pickHorizonForecast(
  forecasts: DemandSupplyForecast[],
  targetHorizon: number,
): DemandSupplyForecast | null {
  if (forecasts.length === 0) return null;
  const exact = forecasts.find((f) => f.horizon_months === targetHorizon);
  if (exact) return exact;
  return [...forecasts].sort((a, b) => b.horizon_months - a.horizon_months)[0];
}

/** The deficit_index for a scenario at the target horizon (+ the horizon used). */
export interface ScenarioDeficit {
  value: number | null;
  horizon: number | null;
}

export function deficitForScenario(
  key: ScenarioKey,
  scenarios: ReportScenarios,
  scenariosSummary: ScenariosSummary | null,
  targetHorizon: number,
): ScenarioDeficit {
  const sc = scenarios.by_scenario[key];
  const fc = sc ? pickHorizonForecast(sc.forecasts, targetHorizon) : null;
  if (fc) return { value: fc.deficit_index, horizon: fc.horizon_months };
  if (scenariosSummary)
    return { value: scenariosSummary[key], horizon: targetHorizon };
  return { value: null, horizon: null };
}
