"use client";

import type {
  MarketTrend,
  MarketTrendStatus,
  OfferTrend,
  OfferTrendPoint,
} from "@/types/site-finder";

interface Props {
  trend?: MarketTrend | null;
}

const LABEL_COLORS: Record<string, { bg: string; color: string }> = {
  "Сильный рост": { bg: "#dcfce7", color: "#15803d" },
  "Умеренный рост": { bg: "#dbeafe", color: "#1d4ed8" },
  Стагнация: { bg: "#fef3c7", color: "#b45309" },
  Падение: { bg: "#fecaca", color: "#b91c1c" },
};

const N_WEAK = 30;
const N_STRONG = 100;

function trendArrow(delta: number): string {
  if (delta > 1) return "↑";
  if (delta < -1) return "↓";
  return "→";
}

function deltaColor(delta: number): string {
  if (delta > 1) return "#15803d";
  if (delta < -1) return "#b91c1c";
  return "#6b7280";
}

function fmtPrice(v: number): string {
  return v.toLocaleString("ru-RU", { maximumFractionDigits: 0 });
}

/**
 * Росреестр отдаёт сделки ПОКВАРТАЛЬНО без точных дат: max(deal_date)=2026-01-01
 * означает «поставка за I квартал 2026», а НЕ «источник встал в январе». Дата
 * YYYY-MM-DD → «I квартал 2026» (римские I/II/III/IV по месяцу). null при
 * отсутствии/некорректной дате. Парсим компоненты напрямую (не new Date() — TZ).
 */
const ROMAN_QUARTERS = ["I", "II", "III", "IV"];

function formatDealsQuarter(asOf: string | undefined | null): string | null {
  if (!asOf) return null;
  const m = /^(\d{4})-(\d{2})/.exec(asOf);
  if (!m) return null;
  const year = Number(m[1]);
  const month = Number(m[2]);
  if (month < 1 || month > 12) return null;
  const quarter = ROMAN_QUARTERS[Math.floor((month - 1) / 3)];
  return `${quarter} квартал ${year}`;
}

/**
 * #2178: дата YYYY-MM-DD → «DD.MM» или «DD.MM.YYYY» (при withYear). Парсим
 * компоненты напрямую — НЕ через new Date() (TZ-сдвиг на полночь UTC).
 */
function formatShortDate(iso: string, withYear: boolean): string | null {
  const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso);
  if (!m) return null;
  const [, year, month, day] = m;
  return withYear ? `${day}.${month}.${year}` : `${day}.${month}`;
}

/** #2178: «DD.MM–DD.MM.YYYY» для диапазона точек тренда (минус — Unicode en-dash). */
function formatPeriod(points: OfferTrendPoint[]): string | null {
  if (points.length === 0) return null;
  const first = formatShortDate(points[0].date, false);
  const last = formatShortDate(points[points.length - 1].date, true);
  if (first == null || last == null) return null;
  return `${first}–${last}`;
}

/**
 * #2178: знаковый delta-процент с Unicode-минусом (−, не дефис) и одним знаком.
 * `+8.1%` / `−8.1%` / `0.0%`.
 */
function formatSignedPct(delta: number): string {
  const rounded = delta.toFixed(1);
  if (delta > 0) return `+${rounded}%`;
  if (delta < 0) return `−${rounded.replace("-", "")}%`;
  return `${rounded}%`;
}

/** #2178: цвет delta-бейджа предложения — danger при падении, success при росте. */
function offerDeltaStyle(delta: number): { bg: string; color: string } {
  if (delta > 1) return { bg: "#dcfce7", color: "#15803d" };
  if (delta < -1) return { bg: "#fecaca", color: "#b91c1c" };
  return { bg: "#f3f4f6", color: "#374151" };
}

/**
 * #2178: SVG-спарклайн по точкам медианы предложения. Одиночная линия — цвет
 * #374151 (правило ui-tokens: цвет серии только для сравнения). Без зависимостей.
 * Каждая точка — <title> с датой и ценой «₽/м²» (native hover-tooltip с единицей).
 */
function OfferSparkline({ points }: { points: OfferTrendPoint[] }) {
  const W = 260;
  const H = 48;
  const PAD = 4;
  if (points.length < 2) return null;

  const values = points.map((p) => p.median_price_m2);
  const min = Math.min(...values);
  const max = Math.max(...values);
  const span = max - min || 1;
  const stepX = (W - PAD * 2) / (points.length - 1);

  const coords = points.map((p, i) => {
    const x = PAD + i * stepX;
    // Инвертируем Y: выше цена — выше на графике (меньше y).
    const y = PAD + (1 - (p.median_price_m2 - min) / span) * (H - PAD * 2);
    return { x, y };
  });

  const line = coords
    .map((c) => `${c.x.toFixed(1)},${c.y.toFixed(1)}`)
    .join(" ");

  return (
    <svg
      width="100%"
      height={H}
      viewBox={`0 0 ${W} ${H}`}
      preserveAspectRatio="none"
      role="img"
      aria-label="Динамика медианной цены предложения, ₽/м²"
      style={{ display: "block", overflow: "visible" }}
    >
      <polyline
        points={line}
        fill="none"
        stroke="#374151"
        strokeWidth={1.5}
        strokeLinejoin="round"
        strokeLinecap="round"
        vectorEffect="non-scaling-stroke"
      />
      {coords.map((c, i) => (
        <circle key={i} cx={c.x} cy={c.y} r={2} fill="#374151">
          <title>
            {formatShortDate(points[i].date, true) ?? points[i].date} ·{" "}
            {fmtPrice(points[i].median_price_m2)} ₽/м²
          </title>
        </circle>
      ))}
    </svg>
  );
}

/**
 * #2178: полноценная карточка тренда по предложению (Объектив) для status
 * "offer_only". Нейтральные токены (--fg-primary / --bg-card), НЕ выглядит
 * ошибкой. deals_stale управляет второй строкой-caveat.
 */
function OfferOnlyCard({
  title,
  offer,
  dealsStale,
  dealsAsOfDate,
}: {
  title: string;
  offer: OfferTrend;
  dealsStale: boolean;
  dealsAsOfDate: string | null | undefined;
}) {
  const latest = offer.points[offer.points.length - 1];
  const delta = offer.delta_pct;
  const period = formatPeriod(offer.points);
  const deltaStyle = delta != null ? offerDeltaStyle(delta) : null;

  // Источник — полным предложением: «По ценам предложения N ЖК рядом (Объектив,
  // M лотов) · DD.MM–DD.MM.YYYY».
  const lots = offer.lots_latest;
  const sourceParts = [
    `По ценам предложения ${offer.complexes_covered} ЖК рядом`,
    lots != null ? `(Объектив, ${fmtPrice(lots)} лотов)` : "(Объектив)",
  ];
  const sourceLine =
    sourceParts.join(" ") + (period != null ? ` · ${period}` : "");

  // Caveat — почему показываем предложение вместо сделок. Сделки Росреестра
  // приходят ПОКВАРТАЛЬНО (max(deal_date) = начало квартала поставки) — это НЕ
  // «источник устарел», а нормальный лаг квартальной выгрузки. Честная копия.
  const dealsQuarter = formatDealsQuarter(dealsAsOfDate);
  const caveat = dealsStale
    ? dealsQuarter != null
      ? `Сделки Росреестра — за ${dealsQuarter} (поставка поквартальная); показана динамика цен предложения (Объектив).`
      : "Сделки Росреестра поставляются поквартально; показана динамика цен предложения (Объектив)."
    : "Сделок Росреестра рядом нет — показана динамика цен предложения (Объектив).";

  return (
    <div
      style={{
        borderRadius: 10,
        padding: "14px 16px",
        background: "#ffffff",
        border: "1px solid #e5e7eb",
        display: "flex",
        flexDirection: "column",
        gap: 8,
      }}
    >
      <div style={{ fontSize: 12, fontWeight: 700, color: "#374151" }}>
        {title}
      </div>

      {/* Main value: текущая медиана предложения + delta-бейдж за период */}
      <div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
        <span
          style={{
            fontSize: 24,
            fontWeight: 800,
            color: "#111827",
            lineHeight: 1,
          }}
        >
          {fmtPrice(latest.median_price_m2)} ₽/м²
        </span>
        {delta != null && deltaStyle != null && (
          <span
            style={{
              display: "inline-block",
              borderRadius: 6,
              padding: "2px 8px",
              background: deltaStyle.bg,
              color: deltaStyle.color,
              fontSize: 13,
              fontWeight: 700,
            }}
          >
            {formatSignedPct(delta)}
          </span>
        )}
      </div>
      <div style={{ fontSize: 12, color: "#6b7280", marginTop: -4 }}>
        медиана предложения · за период
      </div>

      {/* Мини-график динамики предложения */}
      <div style={{ marginTop: 2 }}>
        <OfferSparkline points={offer.points} />
      </div>

      {/* Источник полным предложением + caveat */}
      <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
        <div style={{ fontSize: 11, color: "#6b7280" }}>{sourceLine}</div>
        <div style={{ fontSize: 11, color: "#9ca3af" }}>{caveat}</div>
      </div>
    </div>
  );
}

/** Приглушённое caveat-состояние (status-карточка без фейкового тренда). */
function TrendCaveat({ title, message }: { title: string; message: string }) {
  return (
    <div
      style={{
        borderRadius: 10,
        padding: "14px 16px",
        background: "#f3f4f6",
        display: "flex",
        flexDirection: "column",
        gap: 6,
      }}
    >
      <div style={{ fontSize: 12, fontWeight: 700, color: "#374151" }}>
        {title}
      </div>
      <div style={{ fontSize: 13, color: "#9ca3af" }}>{message}</div>
    </div>
  );
}

export function MarketTrendBlock({ trend }: Props) {
  if (!trend) {
    return (
      <TrendCaveat
        title="Тренд рынка"
        message="Недостаточно сделок ДДУ в радиусе для тренда"
      />
    );
  }

  // P2 (#1871): отсутствие status трактуем как "ok" (старый/кэшированный ответ).
  const status: MarketTrendStatus = trend.status ?? "ok";
  const radiusSuffix =
    trend.radius_km != null ? ` в радиусе ${trend.radius_km} км` : "";
  const title = `Тренд рынка${radiusSuffix}`;

  // #2178: сделок в recent-окне нет (поквартальная поставка / нет рядом), но живёт
  // динамика предложения — полноценная карточка тренда по предложению (Объектив).
  if (status === "offer_only") {
    const offer = trend.offer_trend;
    // Defensive: без валидного offer-блока падаем в честный caveat, не крашимся.
    if (offer && offer.points.length > 0) {
      return (
        <OfferOnlyCard
          title={title}
          offer={offer}
          dealsStale={trend.deals_stale ?? false}
          dealsAsOfDate={trend.deals_as_of_date}
        />
      );
    }
    return (
      <TrendCaveat
        title={title}
        message="Сделки Росреестра поставляются поквартально; тренд по сделкам не показываем."
      />
    );
  }

  // #1871/quarterly: сделки Росреестра приходят поквартально (as_of_date = начало
  // квартала поставки), НЕ «устарели». Показываем честную квартальную подпись
  // вместо тренда (recent-окно пусто, offer-данных тоже нет). Бэк-label в приоритете.
  if (status === "source_stale") {
    const quarter = formatDealsQuarter(trend.as_of_date);
    const message =
      trend.label ??
      (quarter != null
        ? `Сделки Росреестра — за ${quarter} (поставка поквартальная); динамику цен предложения показать не удалось.`
        : "Сделки Росреестра поставляются поквартально; тренд по сделкам не показываем.");
    return <TrendCaveat title={title} message={message} />;
  }

  // P2 (#1871): нет сделок в радиусе за период.
  if (status === "no_deals") {
    return (
      <TrendCaveat title={title} message="Нет сделок в радиусе за период." />
    );
  }

  // status === "ok" — старый контракт с полными числовыми полями.
  const n = trend.recent_deals_count;

  // Без числовых полей (defensive) — показываем no-data, не падаем.
  if (
    trend.delta_6m_pct == null ||
    trend.recent_avg_price_per_m2 == null ||
    trend.prior_avg_price_per_m2 == null ||
    trend.prior_deals_count == null
  ) {
    return (
      <TrendCaveat
        title={title}
        message="Недостаточно сделок ДДУ в радиусе для тренда"
      />
    );
  }

  // n < 30 — hide trend entirely, show data-insufficient state
  if (n < N_WEAK) {
    return (
      <TrendCaveat
        title={title}
        message={`Недостаточно данных (n=${n}) — расширьте радиус для анализа тренда`}
      />
    );
  }

  const delta = trend.delta_6m_pct;
  const arrow = trendArrow(delta);
  const arrowColor = deltaColor(delta);
  // Backend кладёт длинный label ("Сильный рост — рынок растёт быстрее
  // инфляции"); ключи LABEL_COLORS — короткие, поэтому нормализуем по префиксу.
  const label = trend.label ?? "";
  const labelKey = label.split(" — ")[0];
  const labelStyle = LABEL_COLORS[labelKey] ?? {
    bg: "#f3f4f6",
    color: "#374151",
  };

  return (
    <div
      style={{
        borderRadius: 10,
        padding: "14px 16px",
        background: "#fafafa",
        border: "1px solid #e5e7eb",
        display: "flex",
        flexDirection: "column",
        gap: 8,
      }}
    >
      <div style={{ fontSize: 12, fontWeight: 700, color: "#374151" }}>
        {title}
      </div>

      {/* Main price */}
      <div style={{ display: "flex", alignItems: "baseline", gap: 6 }}>
        <span
          style={{
            fontSize: 24,
            fontWeight: 800,
            color: "#111827",
            lineHeight: 1,
          }}
        >
          {fmtPrice(trend.recent_avg_price_per_m2)} ₽/м²
        </span>
      </div>
      <div style={{ fontSize: 12, color: "#6b7280", marginTop: -4 }}>
        за последние 6 мес · {trend.recent_deals_count} сделок
      </div>

      {/* Delta */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 4,
          fontSize: 16,
          fontWeight: 700,
          color: arrowColor,
        }}
      >
        <span>{arrow}</span>
        <span>
          {delta > 0 ? "+" : ""}
          {delta.toFixed(1)}%
        </span>
      </div>

      {/* Prior comparison */}
      <div style={{ fontSize: 11, color: "#9ca3af" }}>
        vs {fmtPrice(trend.prior_avg_price_per_m2)} ₽/м² за предыдущие 6 мес (
        {trend.prior_deals_count}&rarr;{trend.recent_deals_count} сделок)
      </div>

      {/* Label badge */}
      {label && (
        <div
          style={{
            display: "inline-block",
            borderRadius: 6,
            padding: "3px 10px",
            background: labelStyle.bg,
            color: labelStyle.color,
            fontSize: 12,
            fontWeight: 600,
            alignSelf: "flex-start",
            marginTop: 2,
          }}
        >
          {label}
        </div>
      )}

      {/* #2178: компактная вторая строка динамики предложения под сделко-трендом. */}
      {trend.offer_trend &&
        trend.offer_trend.points.length > 0 &&
        (() => {
          const offer = trend.offer_trend;
          const latest = offer.points[offer.points.length - 1];
          const deltaTxt =
            offer.delta_pct != null
              ? ` · Δ ${formatSignedPct(offer.delta_pct)}`
              : "";
          return (
            <div style={{ fontSize: 11, color: "#6b7280" }}>
              Предложение: медиана {fmtPrice(latest.median_price_m2)} ₽/м²
              {deltaTxt} (Объектив)
            </div>
          );
        })()}

      {/* Weak data warning: 30 ≤ n < 100 */}
      {n < N_STRONG && (
        <div className="bg-amber-50 border border-amber-200 text-amber-800 text-xs px-2 py-1 rounded">
          Слабые данные (n={n}) — расширьте радиус для точности
        </div>
      )}
    </div>
  );
}
