"use client";

/**
 * 6.6 Будущее предложение и конкуренты — §13.3 future_market evidence (#950/#949).
 *
 * The §16-traceability evidence BEHIND the supply forecast. 6.1's per-horizon
 * table shows the aggregate deficit; this block surfaces the two detail layers
 * that, until now, lived only in the exports:
 *
 *   • Supply-pressure panel (from `future_market.future_supply`, §9.3) — the
 *     FutureSupplyPressure breakdown as labeled stat cells: открытый сток /
 *     скрытый запас / поглощение / месяцев давления / будущий слой в горизонте,
 *     with district + premise_kind + horizon context + a confidence badge. The
 *     pressure index (∈ 0…1) gets a token bar — higher = more queued supply.
 *   • Future-competitors table (from `future_market.future_competitors`, §9.7) —
 *     the relevance-weighted pipeline competition, sorted by relevance_weight
 *     desc, with a 0…1 token bar for relevance.
 *
 * RU labels reuse the established export wording (report_pdf / excel
 * `_future_supply_pairs`): «Открытый сток», «Скрытый запас», «Будущий слой в
 * горизонте», «Поглощение», «Месяцев давления», «Индекс давления».
 *
 * GRACEFUL: returns null when BOTH future_supply and future_competitors are
 * absent/empty; each part is guarded independently; a null metric renders «нет
 * данных» (never a 0-bar implying a real zero); an empty competitor list skips
 * the table entirely. No crash on a partial / 202-pending report.
 */

import type {
  ConfidenceLevel,
  FutureCompetitor,
  FutureSupply,
  FutureSupplyBreakdown,
} from "@/types/forecast";

import { Badge } from "@/components/ui/Badge";
import {
  CONFIDENCE_RU,
  confidenceVariant,
  fmtNum,
  hasSupplySignal,
} from "./forecast-helpers";

interface Props {
  /** §9.3 future-supply pressure (evidence behind the supply forecast). */
  futureSupply: FutureSupply | null;
  /** §9.7 relevance-weighted pipeline competitors. */
  futureCompetitors: FutureCompetitor[];
}

const NO_DATA = "нет данных";

const SUBHEAD_STYLE: React.CSSProperties = {
  fontSize: 11,
  fontWeight: 500,
  letterSpacing: "0.04em",
  textTransform: "uppercase",
  color: "var(--fg-secondary)",
};

const HINT_STYLE: React.CSSProperties = {
  margin: 0,
  fontSize: 12,
  lineHeight: 1.5,
  color: "var(--fg-tertiary)",
};

// ── ForecastFutureSupplyBlock ────────────────────────────────────────────────────

export function ForecastFutureSupplyBlock({
  futureSupply,
  futureCompetitors,
}: Props) {
  const showSupply = hasSupplySignal(futureSupply);
  const competitors = futureCompetitors.filter(
    (c): c is FutureCompetitor => c != null && typeof c.obj_id === "number",
  );
  const showCompetitors = competitors.length > 0;

  // Graceful: nothing meaningful in either part → render nothing.
  if (!showSupply && !showCompetitors) return null;

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
      {showSupply && futureSupply && (
        <SupplyPressurePanel supply={futureSupply} />
      )}
      {showCompetitors && <CompetitorsTable competitors={competitors} />}
    </div>
  );
}

// ── Supply-pressure panel (§9.3) ─────────────────────────────────────────────────

function SupplyPressurePanel({ supply }: { supply: FutureSupply }) {
  const b = supply.breakdown;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {/* Header: subhead + context (район · помещение · горизонт) + confidence. */}
      <div
        style={{
          display: "flex",
          flexWrap: "wrap",
          alignItems: "center",
          gap: 8,
        }}
      >
        <span style={SUBHEAD_STYLE}>Давление будущего предложения</span>
        <SupplyContext supply={supply} />
        <ConfidencePill level={supply.confidence} />
      </div>

      {/* Pressure index — token bar (∈ 0…1, higher = more queued supply). */}
      <PressureIndexBar index={supply.index} />

      {/* Breakdown — labeled stat cells (the §16 evidence). */}
      <StatGrid breakdown={b} />

      <p style={HINT_STYLE}>
        Месяцев давления — сколько месяцев конкурирующего предложения (скрытый
        запас плюс будущий слой) стоит в очереди при текущем темпе поглощения.
        Индекс давления ∈ 0…1: выше — больше грядущего предложения относительно
        скорости рынка.
      </p>
    </div>
  );
}

function SupplyContext({ supply }: { supply: FutureSupply }) {
  const parts: string[] = [];
  if (supply.district) parts.push(supply.district);
  if (supply.premise_kind) parts.push(supply.premise_kind);
  parts.push(`горизонт ${supply.horizon_months} мес.`);
  if (parts.length === 0) return null;
  return (
    <span style={{ fontSize: 12, color: "var(--fg-tertiary)" }}>
      {parts.join(" · ")}
    </span>
  );
}

function ConfidencePill({ level }: { level: ConfidenceLevel }) {
  return (
    <Badge variant={confidenceVariant(level)} size="sm">
      уверенность {CONFIDENCE_RU[level]}
    </Badge>
  );
}

function PressureIndexBar({ index }: { index: number | null }) {
  const hasValue = index != null;
  const widthPct = hasValue ? Math.max(0, Math.min(100, index * 100)) : 0;
  const valueStr = hasValue ? fmtNum(index, 2) : NO_DATA;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
      <div
        style={{
          display: "flex",
          alignItems: "baseline",
          justifyContent: "space-between",
          gap: 12,
        }}
      >
        <span style={{ fontSize: 13, color: "var(--fg-primary)" }}>
          Индекс давления
        </span>
        <span
          style={{
            fontSize: 12,
            color: hasValue ? "var(--fg-secondary)" : "var(--fg-tertiary)",
            fontVariantNumeric: "tabular-nums",
            flexShrink: 0,
          }}
        >
          {valueStr}
        </span>
      </div>
      <div
        style={{
          position: "relative",
          height: 8,
          borderRadius: 6,
          background: "var(--bg-card-alt)",
          border: "1px solid var(--border-soft)",
          overflow: "hidden",
        }}
        role="img"
        aria-label={`Индекс давления: ${valueStr}`}
      >
        <div
          style={{
            position: "absolute",
            insetBlock: 0,
            insetInlineStart: 0,
            width: `${widthPct}%`,
            // Pressure is a risk signal — accent fill (neutral valence, not
            // success/danger): the index value carries the meaning, not colour.
            background: "var(--accent)",
            borderRadius: 6,
          }}
        />
      </div>
    </div>
  );
}

// ── Breakdown stat cells ─────────────────────────────────────────────────────────

interface StatCell {
  label: string;
  value: number | null;
  digits: number;
}

function StatGrid({ breakdown }: { breakdown: FutureSupplyBreakdown }) {
  // RU labels reuse the export wording (report_pdf / excel _future_supply_pairs).
  const cells: StatCell[] = [
    { label: "Открытый сток, ед.", value: breakdown.open_units, digits: 0 },
    { label: "Скрытый запас, ед.", value: breakdown.hidden_units, digits: 0 },
    {
      label: "Будущий слой в горизонте, ед.",
      value: breakdown.future_units_by_horizon,
      digits: 1,
    },
    {
      label: "Поглощение, ед./мес",
      value: breakdown.monthly_absorption_units,
      digits: 1,
    },
    {
      label: "Месяцев давления",
      value: breakdown.months_of_pressure,
      digits: 1,
    },
  ];

  return (
    <div
      style={{
        display: "grid",
        gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
        gap: 8,
      }}
    >
      {cells.map((c) => (
        <StatCellView key={c.label} cell={c} />
      ))}
    </div>
  );
}

function StatCellView({ cell }: { cell: StatCell }) {
  const { value } = cell;
  const hasValue = value != null;
  const valueStr = hasValue ? fmtNum(value, cell.digits) : NO_DATA;
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: 4,
        padding: "10px 12px",
        background: "var(--bg-card-alt)",
        border: "1px solid var(--border-soft)",
        borderRadius: 8,
      }}
    >
      <span style={SUBHEAD_STYLE}>{cell.label}</span>
      <span
        style={{
          fontSize: 18,
          fontWeight: 600,
          color: hasValue ? "var(--fg-primary)" : "var(--fg-tertiary)",
          fontVariantNumeric: "tabular-nums",
        }}
      >
        {valueStr}
      </span>
    </div>
  );
}

// ── Future-competitors table (§9.7) ──────────────────────────────────────────────

const TH_STYLE: React.CSSProperties = {
  textAlign: "left",
  padding: "8px 12px",
  fontSize: 11,
  fontWeight: 500,
  letterSpacing: "0.04em",
  textTransform: "uppercase",
  color: "var(--fg-secondary)",
  whiteSpace: "nowrap",
  borderBottom: "1px solid var(--border-card)",
};

const TD_STYLE: React.CSSProperties = {
  padding: "10px 12px",
  fontSize: 13,
  color: "var(--fg-primary)",
  verticalAlign: "middle",
  borderBottom: "1px solid var(--border-soft)",
  fontVariantNumeric: "tabular-nums",
};

const NUM_TD: React.CSSProperties = { ...TD_STYLE, textAlign: "right" };
const NUM_TH: React.CSSProperties = { ...TH_STYLE, textAlign: "right" };

function CompetitorsTable({
  competitors,
}: {
  competitors: FutureCompetitor[];
}) {
  // Sort by relevance_weight desc; nulls sink to the bottom (no fabricated 0).
  const rows = [...competitors].sort(
    (a, b) => (b.relevance_weight ?? -1) - (a.relevance_weight ?? -1),
  );

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <span style={SUBHEAD_STYLE}>Будущие конкуренты ({rows.length})</span>
      <div style={{ overflowX: "auto" }}>
        <table
          style={{
            width: "100%",
            borderCollapse: "collapse",
            minWidth: 640,
          }}
        >
          <thead>
            <tr>
              <th style={TH_STYLE}>Название</th>
              <th style={TH_STYLE}>Класс</th>
              <th style={NUM_TH}>Расстояние</th>
              <th style={NUM_TH}>Квартир</th>
              <th style={NUM_TH}>Скорость/мес</th>
              <th style={{ ...TH_STYLE, minWidth: 140 }}>Релевантность</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((c) => (
              <CompetitorRow key={c.obj_id} competitor={c} />
            ))}
          </tbody>
        </table>
      </div>
      <p style={HINT_STYLE}>
        Релевантность ∈ 0…1 — взвешенный сигнал близости, класса, цены и стадии
        к горизонту (§9.7). Список — top-N будущих конкурентов по релевантности.
      </p>
    </div>
  );
}

function CompetitorRow({ competitor }: { competitor: FutureCompetitor }) {
  const name = competitor.comm_name?.trim() || "Без названия";
  const rw = competitor.relevance_weight;
  return (
    <tr>
      <td style={{ ...TD_STYLE, maxWidth: 280 }}>
        <span
          title={name}
          style={{
            display: "block",
            overflow: "hidden",
            textOverflow: "ellipsis",
            whiteSpace: "nowrap",
          }}
        >
          {name}
        </span>
      </td>
      <td style={TD_STYLE}>
        {competitor.obj_class ? (
          <Badge variant="neutral" size="sm">
            {competitor.obj_class}
          </Badge>
        ) : (
          <span style={{ color: "var(--fg-tertiary)" }}>{NO_DATA}</span>
        )}
      </td>
      <td style={NUM_TD}>
        {competitor.distance_m != null
          ? `${fmtNum(competitor.distance_m, 0)} м`
          : NO_DATA}
      </td>
      <td style={NUM_TD}>
        {competitor.flats_total != null
          ? competitor.flats_total.toLocaleString("ru")
          : NO_DATA}
      </td>
      <td style={NUM_TD}>
        {competitor.velocity_per_month != null
          ? fmtNum(competitor.velocity_per_month, 1)
          : NO_DATA}
      </td>
      <td style={TD_STYLE}>
        <RelevanceBar value={rw} />
      </td>
    </tr>
  );
}

function RelevanceBar({ value }: { value: number | null }) {
  const hasValue = value != null;
  const widthPct = hasValue ? Math.max(0, Math.min(100, value * 100)) : 0;
  const valueStr = hasValue ? fmtNum(value, 2) : NO_DATA;
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      <div
        style={{
          position: "relative",
          flex: 1,
          minWidth: 64,
          height: 8,
          borderRadius: 6,
          background: "var(--bg-card-alt)",
          border: "1px solid var(--border-soft)",
          overflow: "hidden",
        }}
        role="img"
        aria-label={`Релевантность: ${valueStr}`}
      >
        <div
          style={{
            position: "absolute",
            insetBlock: 0,
            insetInlineStart: 0,
            width: `${widthPct}%`,
            background: "var(--accent)",
            borderRadius: 6,
          }}
        />
      </div>
      <span
        style={{
          fontSize: 12,
          color: hasValue ? "var(--fg-secondary)" : "var(--fg-tertiary)",
          fontVariantNumeric: "tabular-nums",
          flexShrink: 0,
          minWidth: 36,
          textAlign: "right",
        }}
      >
        {valueStr}
      </span>
    </div>
  );
}
