"use client";

import Link from "next/link";
import { X } from "lucide-react";

import { Badge } from "@/components/ui/Badge";
import type { BadgeVariant } from "@/components/ui/Badge";
import type { GateVerdictLabel } from "@/types/site-finder";

// ── Per-column state ──────────────────────────────────────────────────────────

/**
 * One parcel column. `status` mirrors the TanStack Query lifecycle of the
 * per-cad `useParcelAnalyzeQuery` lifted up by the page. Metrics are flattened
 * to primitives here so CompareTable stays a pure presentational component.
 */
export interface CompareColumn {
  cad: string;
  status: "loading" | "error" | "ready";
  errorMsg?: string;
  districtName?: string | null;
  verdictLabel?: GateVerdictLabel | null;
  score?: number | null;
  scoreLabel?: string | null;
  velocityScore?: number | null; // 0..1
  // False → конкуренты есть, но данных velocity нет (velocity_score=0 — sentinel,
  // не факт «рынок стоит»). Когда false, ячейка velocity = «—» и не участвует в
  // подсветке «лучшее». undefined трактуется как «данные есть» (обратная совместимость).
  velocityDataAvailable?: boolean | null;
  medianPricePerM2?: number | null;
  pipeline24mo?: number | null; // total flats in 24-month pipeline
  confidenceLabel?: "high" | "medium" | "low" | null;
  confidenceValue?: number | null; // 0..1
}

interface Props {
  columns: CompareColumn[];
  onRemove: (cad: string) => void;
}

// ── Metric row definitions ──────────────────────────────────────────────────

type WinnerDir = "high" | "low" | "none";

interface MetricRow {
  key: string;
  label: string;
  /** Which direction wins, for per-row highlight. "none" → not comparable. */
  winner: WinnerDir;
  /** Numeric value used for winner comparison (null = no data, never wins). */
  value: (c: CompareColumn) => number | null;
  /** Rendered cell content. */
  render: (c: CompareColumn) => React.ReactNode;
}

const VERDICT_BADGE: Record<GateVerdictLabel, BadgeVariant> = {
  Можно: "success",
  Нельзя: "danger",
  "С ограничениями": "warning",
  "Нужна проверка": "neutral",
};

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

const DASH = "—";

function fmtScore(v: number | null | undefined): string {
  return v != null && Number.isFinite(v) ? v.toFixed(1) : DASH;
}

function fmtPrice(v: number | null | undefined): string {
  // Median ₽/м² — точное число с разделителями тысяч (ru), e.g. «145 320 ₽».
  return v != null && Number.isFinite(v)
    ? `${Math.round(v).toLocaleString("ru")} ₽`
    : DASH;
}

function fmtPipeline(v: number | null | undefined): string {
  return v != null && Number.isFinite(v)
    ? `${Math.round(v).toLocaleString("ru")} кв.`
    : DASH;
}

const METRIC_ROWS: MetricRow[] = [
  {
    key: "verdict",
    label: "Вердикт МКД",
    winner: "none",
    value: () => null,
    render: (c) =>
      c.verdictLabel ? (
        <Badge variant={VERDICT_BADGE[c.verdictLabel]} size="sm">
          {c.verdictLabel}
        </Badge>
      ) : (
        DASH
      ),
  },
  {
    key: "score",
    label: "POI-скор · 0–40",
    winner: "high",
    value: (c) => c.score ?? null,
    render: (c) => (
      <span style={{ fontVariantNumeric: "tabular-nums" }}>
        {fmtScore(c.score)}
        {c.scoreLabel ? (
          <span style={{ color: "var(--fg-tertiary)", fontSize: 12 }}>
            {" "}
            · {c.scoreLabel}
          </span>
        ) : null}
      </span>
    ),
  },
  {
    key: "velocity",
    label: "Скорость продаж",
    winner: "high",
    // velocity_score=0 при velocity_data_available=false — это «нет данных», а не
    // реальный 0, поэтому такая колонка не должна участвовать в сравнении/подсветке.
    value: (c) =>
      c.velocityDataAvailable === false ? null : c.velocityScore ?? null,
    render: (c) =>
      c.velocityDataAvailable !== false &&
      c.velocityScore != null &&
      Number.isFinite(c.velocityScore) ? (
        <span style={{ fontVariantNumeric: "tabular-nums" }}>
          {Math.round(c.velocityScore * 100)}%
        </span>
      ) : (
        DASH
      ),
  },
  {
    key: "price",
    label: "Медиана ₽ / м²",
    // Lower median price = cheaper land context. Valence is ambiguous for a
    // developer (cheaper district ≠ better), so it is NOT highlighted.
    winner: "none",
    value: (c) => c.medianPricePerM2 ?? null,
    render: (c) => (
      <span style={{ fontVariantNumeric: "tabular-nums" }}>
        {fmtPrice(c.medianPricePerM2)}
      </span>
    ),
  },
  {
    key: "pipeline",
    label: "Пайплайн 24 мес",
    // More competing pipeline = more future supply = worse. Lower wins.
    winner: "low",
    value: (c) => c.pipeline24mo ?? null,
    render: (c) => (
      <span style={{ fontVariantNumeric: "tabular-nums" }}>
        {fmtPipeline(c.pipeline24mo)}
      </span>
    ),
  },
  {
    key: "confidence",
    label: "Достоверность",
    winner: "high",
    value: (c) => c.confidenceValue ?? null,
    render: (c) =>
      c.confidenceLabel ? (
        <span style={{ fontVariantNumeric: "tabular-nums" }}>
          {c.confidenceValue != null
            ? `${Math.round(c.confidenceValue * 100)}% · `
            : ""}
          {CONFIDENCE_RU[c.confidenceLabel]}
        </span>
      ) : (
        DASH
      ),
  },
];

/**
 * Returns the set of column cads that win a given row, or an empty set when the
 * metric is not comparable / has fewer than two data points. Ties win jointly.
 */
function winnersFor(row: MetricRow, columns: CompareColumn[]): Set<string> {
  if (row.winner === "none") return new Set();
  const vals = columns
    .map((c) => ({ cad: c.cad, v: row.value(c) }))
    .filter((x): x is { cad: string; v: number } => x.v != null);
  if (vals.length < 2) return new Set();
  const best =
    row.winner === "high"
      ? Math.max(...vals.map((x) => x.v))
      : Math.min(...vals.map((x) => x.v));
  return new Set(vals.filter((x) => x.v === best).map((x) => x.cad));
}

// ── Component ───────────────────────────────────────────────────────────────

export function CompareTable({ columns, onRemove }: Props) {
  const winnerByRow = new Map<string, Set<string>>(
    METRIC_ROWS.map((row) => [row.key, winnersFor(row, columns)]),
  );

  return (
    <div style={{ overflowX: "auto" }}>
      <table
        style={{
          width: "100%",
          borderCollapse: "collapse",
          fontSize: 14,
          minWidth: 120 + columns.length * 200,
        }}
      >
        <thead>
          <tr>
            <th style={cornerTh}>Фактор</th>
            {columns.map((c) => (
              <th key={c.cad} style={colTh}>
                <div style={colHeadInner}>
                  <Link
                    href={`/site-finder/analysis/${encodeURIComponent(c.cad)}`}
                    style={{
                      color: "var(--accent)",
                      textDecoration: "none",
                      fontFamily: "monospace",
                      fontSize: 13,
                      wordBreak: "break-all",
                    }}
                    title="Открыть полный анализ участка"
                  >
                    {c.cad}
                  </Link>
                  <button
                    type="button"
                    onClick={() => onRemove(c.cad)}
                    aria-label={`Убрать ${c.cad} из сравнения`}
                    style={removeBtn}
                  >
                    <X size={14} strokeWidth={1.5} />
                  </button>
                </div>
                {c.districtName && c.districtName !== DASH ? (
                  <div
                    style={{
                      fontSize: 12,
                      fontWeight: 400,
                      color: "var(--fg-tertiary)",
                      marginTop: 2,
                    }}
                  >
                    {c.districtName}
                  </div>
                ) : null}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {METRIC_ROWS.map((row) => {
            const winners = winnerByRow.get(row.key) ?? new Set<string>();
            return (
              <tr key={row.key} style={{ borderTop: "1px solid var(--border-soft)" }}>
                <th style={rowTh}>{row.label}</th>
                {columns.map((c) => {
                  const isWinner = winners.has(c.cad);
                  return (
                    <td
                      key={c.cad}
                      style={{
                        ...cell,
                        background: isWinner ? "var(--success-soft)" : undefined,
                        color: isWinner ? "var(--success)" : "var(--fg-primary)",
                        fontWeight: isWinner ? 600 : 400,
                      }}
                    >
                      {c.status === "loading" ? (
                        <span style={{ color: "var(--fg-tertiary)" }}>…</span>
                      ) : c.status === "error" ? (
                        <span
                          style={{ color: "var(--danger)", fontSize: 12 }}
                          title={c.errorMsg ?? "Ошибка анализа"}
                        >
                          ошибка
                        </span>
                      ) : (
                        row.render(c)
                      )}
                    </td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ── Styles ────────────────────────────────────────────────────────────────

const baseTh: React.CSSProperties = {
  padding: "10px 12px",
  borderBottom: "1px solid var(--border-card)",
  fontWeight: 600,
  verticalAlign: "top",
};

const cornerTh: React.CSSProperties = {
  ...baseTh,
  textAlign: "left",
  background: "var(--bg-app)",
  width: 180,
  minWidth: 160,
};

const colTh: React.CSSProperties = {
  ...baseTh,
  textAlign: "left",
  background: "var(--bg-app)",
};

const colHeadInner: React.CSSProperties = {
  display: "flex",
  alignItems: "center",
  justifyContent: "space-between",
  gap: 8,
};

const rowTh: React.CSSProperties = {
  padding: "10px 12px",
  textAlign: "left",
  fontWeight: 500,
  color: "var(--fg-secondary)",
  background: "var(--bg-card-alt)",
};

const cell: React.CSSProperties = {
  padding: "10px 12px",
  textAlign: "left",
};

const removeBtn: React.CSSProperties = {
  display: "flex",
  alignItems: "center",
  justifyContent: "center",
  background: "none",
  border: "none",
  padding: 2,
  cursor: "pointer",
  color: "var(--fg-tertiary)",
  flexShrink: 0,
};
