"use client";

/**
 * ScenarioCards — 3 dark cockpit cards (base / aggressive / conservative) from
 * report.scenarios.by_scenario. Each card shows the deficit-index (big, signed,
 * colour by sign) at the target horizon, the demand/supply projection, and the
 * months-of-inventory (MOI). Mirrors the §22 light ScenariosBlock field mapping.
 *
 * #1871 P1 — when backend `compute_scenarios` collapses three scenarios into
 * one (failed §9.6 β rate-sensitivity gate → demand_normalization returns
 * coefficient=1.0 across the envelope), we render ONE «Базовый» card + a
 * caveat note instead of three visually-identical copies. Caveat text is the
 * source-of-truth backend constant `_COLLAPSE_REASON_LOW_BETA`, NEVER hardcoded.
 */

import styles from "@/app/site-finder/analysis/[cad]/ptica/ptica.module.css";
import type {
  DemandSupplyForecast,
  ReportScenarios,
  ScenarioForecast,
  ScenarioKey,
  ScenariosSummary,
} from "@/types/forecast";
import {
  DEFICIT_BALANCE_EPS,
  SCENARIO_ACCENT,
  SCENARIO_HINT,
  SCENARIO_ORDER,
  SCENARIO_RU,
  deficitForScenario,
  deficitTone,
  deficitWord,
  fmtInt,
  fmtNum,
  fmtSignedDeficit,
  pickHorizonForecast,
} from "./scenario-helpers";

interface Props {
  scenarios: ReportScenarios;
  scenariosSummary: ScenariosSummary | null;
  targetHorizon: number;
}

const DEFICIT_TONE_CLASS = {
  good: styles.deficitPos,
  bad: styles.deficitNeg,
  warn: styles.deficitNeg,
  neutral: styles.deficitFlat,
} as const;

const ACCENT_CLASS = {
  base: styles.scAccentBase,
  aggr: styles.scAccentAggr,
  cons: styles.scAccentCons,
} as const;

interface ScenarioCardData {
  value: number | null;
  horizon: number | null;
}

function ScenarioBaseCard({
  scenarioKey,
  sc,
  di,
  fc,
  targetHorizon,
}: {
  scenarioKey: ScenarioKey;
  sc: ScenarioForecast | undefined;
  di: ScenarioCardData;
  fc: DemandSupplyForecast | null;
  targetHorizon: number;
}) {
  // Suppress unused-when-collapsed warning: `sc` is part of the contract so
  // future card surfaces (rate-path) can read it without re-plumbing props.
  void sc;
  const labelHorizon = di.horizon ?? targetHorizon;
  const value = di.value;
  const tone = value != null ? deficitTone(value) : "neutral";
  const word =
    value != null
      ? Math.abs(value) < DEFICIT_BALANCE_EPS
        ? "баланс"
        : deficitWord(value)
      : "нет данных";

  return (
    <div
      className={`${styles.card} ${styles.scenarioCard} ${ACCENT_CLASS[SCENARIO_ACCENT[scenarioKey]]}`}
    >
      <div className={styles.scTag}>{SCENARIO_RU[scenarioKey]}</div>
      <div className={`${styles.scDeficit} ${DEFICIT_TONE_CLASS[tone]}`}>
        {value != null ? fmtSignedDeficit(value) : "—"}
      </div>
      <div className={styles.scKvRow}>
        <span className={styles.scK}>
          Дефицит-индекс ({labelHorizon} мес)
        </span>
        <span className={styles.scV}>{word}</span>
      </div>
      <div className={styles.scKvRow}>
        <span className={styles.scK}>Прогноз спроса</span>
        <span className={styles.scV}>
          {fc ? `${fmtInt(fc.projected_demand_units)} кв` : "—"}
        </span>
      </div>
      <div className={styles.scKvRow}>
        <span className={styles.scK}>Прогноз предложения</span>
        <span className={styles.scV}>
          {fc ? `${fmtInt(fc.projected_supply_units)} кв` : "—"}
        </span>
      </div>
      <div className={styles.scKvRow}>
        <span className={styles.scK}>Месяцев запаса (MOI)</span>
        <span className={styles.scV}>
          {fc ? fmtNum(fc.months_of_inventory, 1) : "—"}
        </span>
      </div>
      <div className={styles.scNote}>{SCENARIO_HINT[scenarioKey]}</div>
    </div>
  );
}

export function ScenarioCards({
  scenarios,
  scenariosSummary,
  targetHorizon,
}: Props) {
  const present = SCENARIO_ORDER.filter(
    (k) => scenarios.by_scenario[k] != null || scenariosSummary != null,
  );

  if (present.length === 0) {
    return (
      <div className={`${styles.panel} ${styles.emptyPanel}`}>
        Сценарный прогноз недоступен.
      </div>
    );
  }

  // #1871 P1 — collapse: ONE «Базовый» card + caveat from backend. Caveat
  // string comes from `scenarios.scenarios_collapse_reason` only — never
  // hardcoded here (backend `_COLLAPSE_REASON_LOW_BETA` is source of truth).
  if (scenarios.scenarios_collapsed === true) {
    const sc = scenarios.by_scenario.base;
    const di = deficitForScenario(
      "base",
      scenarios,
      scenariosSummary,
      targetHorizon,
    );
    const fc = sc ? pickHorizonForecast(sc.forecasts, targetHorizon) : null;
    return (
      <section className={styles.scenarioGrid}>
        <ScenarioBaseCard
          scenarioKey="base"
          sc={sc}
          di={di}
          fc={fc}
          targetHorizon={targetHorizon}
        />
        {scenarios.scenarios_collapse_reason && (
          <div className={styles.scenarioCollapsedNote}>
            {/* #1963 — заголовок-вопрос вместо немой плашки с причиной. */}
            <div className={styles.scenarioCollapsedTitle}>
              Почему один сценарий, а не три
            </div>
            {scenarios.scenarios_collapse_reason}
          </div>
        )}
      </section>
    );
  }

  return (
    <section className={styles.scenarioGrid}>
      {present.map((key) => {
        const sc = scenarios.by_scenario[key];
        const di = deficitForScenario(
          key,
          scenarios,
          scenariosSummary,
          targetHorizon,
        );
        const fc = sc ? pickHorizonForecast(sc.forecasts, targetHorizon) : null;
        return (
          <ScenarioBaseCard
            key={key}
            scenarioKey={key}
            sc={sc}
            di={di}
            fc={fc}
            targetHorizon={targetHorizon}
          />
        );
      })}
    </section>
  );
}
