"use client";

/**
 * 6.4 Прогноз по всем форматам — таблица ассортимента (#1745, фаза 1).
 *
 * Статическая таблица под рекомендацией продукта: строки = форматы (студия / 1к /
 * 2к / 3к / 4-5к) РЕКОМЕНДОВАННОГО класса, колонки = Формат · Индекс дефицита ·
 * Прогноз спроса (квартир) · Сигнал. Цель — показать продуктовому директору весь
 * срез дефицита по форматам одним взглядом (а не только рекомендованный формат).
 *
 * Источник: `product_tz.mix` (квартирография — ячейки формат×класс с per-ячейкой
 * deficit_index + #1745-проброшенными projected_demand_units/signal). Фильтруем к
 * форматам рекомендованного класса, упорядочиваем по канонической комнатной сетке.
 *
 * СЕМАНТИКА (зеркало §22 deficit): deficit_index >0 — недонасыщенность (--success,
 * повод строить), <0 — затоварка (--danger), ≈0 — баланс. Рекомендованный формат
 * (сильнейший дефицит класса) — строка --accent-soft. deficit_index=null → «тонкие
 * данные» серым (--fg-tertiary), НЕ 0 (честность: отсутствие сигнала ≠ нулевой
 * сигнал). Прогноз спроса null → тоже «тонкие данные».
 *
 * БЕЗ слайдеров и без рублей — это фаза 1 (фаза 2 с экономикой/сценариями придёт
 * после бэктеста движка #951). Блок помечен «Советующий расчёт, не основание для
 * инвест-решения».
 *
 * GRACEFUL: returns null когда у рекомендованного класса нет ни одной форматной
 * ячейки (нечего показывать).
 */

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

import { Badge } from "@/components/ui/Badge";
import type { BadgeVariant } from "@/components/ui/Badge";
import {
  DEFICIT_BALANCE_EPS,
  deficitSignalWord,
  deficitVariant,
  fmtNum,
} from "./forecast-helpers";

interface Props {
  /** Рекомендованный класс (§10.2) — фильтр строк таблицы. */
  objClass: string | null;
  /** Квартирография — ячейки формат×класс с deficit_index/прогнозом/сигналом. */
  mix: ProductMixEntry[];
}

// Каноническая комнатная сетка для строк (порядок ОБЯЗАТЕЛЕН: от меньшего к
// большему). Ключ — live bucket-id (вокабуляр overlay), значение — короткая
// RU-метка строки. Неизвестные bucket'ы рисуем как есть в конце.
const ROOM_ROW_ORDER: { bucket: string; label: string }[] = [
  { bucket: "1-Студия", label: "Студия" },
  { bucket: "2-1-к", label: "1-к" },
  { bucket: "3-2-к", label: "2-к" },
  { bucket: "4-3-к", label: "3-к" },
  { bucket: "5-80+ м²", label: "4-5-к" },
];

const ROOM_INDEX: Map<string, number> = new Map(
  ROOM_ROW_ORDER.map((r, i) => [r.bucket, i]),
);

const ROOM_LABEL: Map<string, string> = new Map(
  ROOM_ROW_ORDER.map((r) => [r.bucket, r.label]),
);

// Сигнал-бейдж: вариант по знаку дефицита (строить success / баланс neutral /
// избегать danger). Зеркало deficitVariant, но neutral вместо нейтрального.
function signalVariant(deficitIndex: number): BadgeVariant {
  const v = deficitVariant(deficitIndex);
  if (v === "success") return "success";
  if (v === "danger") return "danger";
  return "neutral";
}

// Цвет ячейки индекса дефицита (только токены): >0 --success, <0 --danger,
// ≈0 нейтрально (--fg-secondary). Зеркало deficitVariant.
function deficitColor(deficitIndex: number): string {
  const v = deficitVariant(deficitIndex);
  if (v === "success") return "var(--success)";
  if (v === "danger") return "var(--danger)";
  return "var(--fg-secondary)";
}

interface AssortmentRow {
  bucket: string;
  label: string;
  deficit_index: number | null;
  projected_demand_units: number | null;
  signal: string | null;
}

function buildRows(
  objClass: string | null,
  mix: ProductMixEntry[],
): AssortmentRow[] {
  // Ячейки рекомендованного класса (или все, если класс не задан — деградация).
  const cells = mix.filter(
    (m) => m.bucket != null && (objClass == null || m.obj_class === objClass),
  );

  // По одной строке на bucket (если дубликаты — берём первую встреченную).
  const byBucket = new Map<string, ProductMixEntry>();
  for (const m of cells) {
    if (m.bucket != null && !byBucket.has(m.bucket)) byBucket.set(m.bucket, m);
  }

  const rows: AssortmentRow[] = [];
  for (const [bucket, m] of byBucket) {
    rows.push({
      bucket,
      label: ROOM_LABEL.get(bucket) ?? bucket,
      deficit_index: m.deficit_index ?? null,
      projected_demand_units: m.projected_demand_units ?? null,
      // Готовый backend-signal в приоритете; иначе деривируем из индекса (fallback).
      signal:
        m.signal ??
        (m.deficit_index != null ? deficitSignalWord(m.deficit_index) : null),
    });
  }

  // Сортируем по канонической сетке; неизвестные bucket'ы — в конец (стабильно).
  rows.sort((a, b) => {
    const ai = ROOM_INDEX.get(a.bucket) ?? ROOM_ROW_ORDER.length;
    const bi = ROOM_INDEX.get(b.bucket) ?? ROOM_ROW_ORDER.length;
    if (ai !== bi) return ai - bi;
    return a.bucket.localeCompare(b.bucket);
  });
  return rows;
}

// Рекомендованный формат = сильнейший дефицит класса (как в ранкинге). null —
// нет ни одной ячейки с измеримым индексом → нечего подсвечивать.
function recommendedBucket(rows: AssortmentRow[]): string | null {
  let best: AssortmentRow | null = null;
  for (const r of rows) {
    if (r.deficit_index == null) continue;
    if (best == null || r.deficit_index > (best.deficit_index ?? -Infinity)) {
      best = r;
    }
  }
  return best?.bucket ?? null;
}

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

const TD_STYLE: React.CSSProperties = {
  fontSize: 13,
  color: "var(--fg-primary)",
  padding: "9px 12px",
  fontVariantNumeric: "tabular-nums",
};

export function ForecastAssortmentBlock({ objClass, mix }: Props) {
  const rows = buildRows(objClass, mix);
  if (rows.length === 0) return null;

  const recoBucket = recommendedBucket(rows);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {/* Headline-bar: один-предложение caveat (--bg-headline + --fg-on-dark) */}
      <div
        style={{
          background: "var(--bg-headline)",
          color: "var(--fg-on-dark)",
          borderRadius: 12,
          padding: "10px 14px",
          fontSize: 12,
          lineHeight: 1.5,
        }}
      >
        Советующий расчёт, не основание для инвест-решения.
      </div>

      {/* Таблица прогноза по всем форматам */}
      <div
        style={{
          border: "1px solid var(--border-card)",
          borderRadius: 12,
          overflowX: "auto",
        }}
      >
        <table
          style={{
            width: "100%",
            borderCollapse: "collapse",
            minWidth: 480,
          }}
        >
          <thead>
            <tr style={{ background: "var(--bg-card-alt)" }}>
              <th style={{ ...TH_STYLE, textAlign: "left" }}>Формат</th>
              <th
                style={{ ...TH_STYLE, textAlign: "right" }}
                title="Индекс дефицита ∈ [−1, +1]: >0 — недонасыщенность (повод строить), <0 — затоварка."
              >
                Индекс дефицита
              </th>
              <th
                style={{ ...TH_STYLE, textAlign: "right" }}
                title="Прогноз спроса на целевом горизонте — сколько квартир рынок поглотит в этом формате."
              >
                Прогноз спроса, квартир
              </th>
              <th style={{ ...TH_STYLE, textAlign: "left" }}>Сигнал</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((r, i) => {
              const isReco = recoBucket != null && r.bucket === recoBucket;
              const di = r.deficit_index;
              const demand = r.projected_demand_units;
              return (
                <tr
                  key={r.bucket}
                  style={{
                    background: isReco
                      ? "var(--accent-soft)"
                      : "var(--bg-card)",
                    borderTop:
                      i === 0 ? "none" : "1px solid var(--border-soft)",
                  }}
                >
                  {/* Формат */}
                  <td
                    style={{
                      ...TD_STYLE,
                      textAlign: "left",
                      fontWeight: isReco ? 600 : 400,
                    }}
                  >
                    <span
                      style={{
                        display: "inline-flex",
                        alignItems: "center",
                        gap: 8,
                      }}
                    >
                      {r.label}
                      {isReco && (
                        <Badge variant="info" size="sm">
                          рекомендован
                        </Badge>
                      )}
                    </span>
                  </td>

                  {/* Индекс дефицита */}
                  <td style={{ ...TD_STYLE, textAlign: "right" }}>
                    {di != null ? (
                      <span
                        style={{ fontWeight: 600, color: deficitColor(di) }}
                      >
                        {di > 0 ? "+" : ""}
                        {fmtNum(di, 2)}
                      </span>
                    ) : (
                      <span style={{ color: "var(--fg-tertiary)" }}>
                        тонкие данные
                      </span>
                    )}
                  </td>

                  {/* Прогноз спроса, квартир */}
                  <td style={{ ...TD_STYLE, textAlign: "right" }}>
                    {demand != null ? (
                      <>
                        {fmtNum(demand, 0)}{" "}
                        <span style={{ color: "var(--fg-tertiary)" }}>кв.</span>
                      </>
                    ) : (
                      <span style={{ color: "var(--fg-tertiary)" }}>
                        тонкие данные
                      </span>
                    )}
                  </td>

                  {/* Сигнал */}
                  <td style={{ ...TD_STYLE, textAlign: "left" }}>
                    {di != null ? (
                      <Badge variant={signalVariant(di)} size="sm">
                        {r.signal ??
                          (Math.abs(di) < DEFICIT_BALANCE_EPS
                            ? "баланс"
                            : deficitSignalWord(di))}
                      </Badge>
                    ) : (
                      <span
                        style={{ color: "var(--fg-tertiary)", fontSize: 12 }}
                      >
                        тонкие данные
                      </span>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}
