"use client";

/**
 * WhatIfPanel — «Что-если» интерактивный пересчёт оценки на результате.
 * Web-преимущество над статичным PDF: продавец/агент крутит ключевые
 * value-drivers (ремонт, этаж, площадь, балкон) и видит, как меняется оценка,
 * не перезаполняя форму. Demo wow: «а если сделать ремонт — вот +X».
 *
 * Использует ТОТ ЖЕ POST /api/v1/trade-in/estimate (useEstimateMutation) — не
 * параллельный API-путь. Запрос дебаунсится (~700 мс) и стреляет только если
 * значение реально изменилось относительно последнего отправленного.
 * Baseline (исходная оценка) держится снаружи и не затрагивается — панель
 * показывает ДЕЛЬТУ к нему и не клобберит остальные карточки страницы.
 *
 * Каждый estimate ходит в скраперы/DaData, поэтому: debounce + skip-if-unchanged
 * + ручная кнопка «Пересчитать». Авто-режим включён по умолчанию (autoMode),
 * но переключается чекбоксом «Авто-пересчёт».
 */
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import type {
  AggregatedEstimate,
  RepairState,
  TradeInEstimateInput,
} from "@/types/trade-in";
import { useEstimateMutation } from "@/lib/trade-in-api";

interface Props {
  /** Исходная оценка-baseline — диффим относительно неё. */
  baseEstimate: AggregatedEstimate;
  /** Исходный input — основа для патчей (модифицируем копию). */
  baseInput: TradeInEstimateInput;
}

const REPAIR_OPTIONS: ReadonlyArray<{ value: RepairState; label: string }> = [
  { value: "needs_repair", label: "Требует ремонта" },
  { value: "standard", label: "Жилое" },
  { value: "good", label: "Хороший" },
  { value: "excellent", label: "Евроремонт" },
];

const DEBOUNCE_MS = 700;

/** Цена-итог, по которой считаем дельту: ожидаемая сделка, иначе медиана. */
function headlinePrice(e: AggregatedEstimate): number {
  const sold = e.expected_sold_price_rub;
  return typeof sold === "number" && sold > 0 ? sold : e.median_price_rub;
}

function formatMln(rub: number): string {
  return `${(rub / 1_000_000).toFixed(2).replace(".", ",")} млн`;
}

function formatDeltaMln(rub: number): string {
  const sign = rub > 0 ? "+" : rub < 0 ? "−" : "";
  const abs = Math.abs(rub);
  return `${sign}${(abs / 1_000_000).toFixed(2).replace(".", ",")} млн ₽`;
}

interface Draft {
  repair_state: RepairState | "";
  floor: number | null;
  area_m2: number;
  has_balcony: boolean;
}

function draftFromInput(input: TradeInEstimateInput, est: AggregatedEstimate): Draft {
  return {
    repair_state: (est.repair_state ?? input.repair_state ?? "") as RepairState | "",
    floor: est.floor ?? input.floor ?? null,
    area_m2: est.area_m2 ?? input.area_m2 ?? 0,
    has_balcony: est.has_balcony ?? input.has_balcony ?? false,
  };
}

/** Сериализуемый ключ драфта — для skip-if-unchanged сравнения. */
function draftKey(d: Draft): string {
  return `${d.repair_state}|${d.floor ?? ""}|${d.area_m2}|${d.has_balcony ? 1 : 0}`;
}

function applyDraft(base: TradeInEstimateInput, d: Draft): TradeInEstimateInput {
  const out: TradeInEstimateInput = {
    ...base,
    area_m2: d.area_m2,
    floor: d.floor,
    has_balcony: d.has_balcony,
  };
  if (d.repair_state) out.repair_state = d.repair_state;
  return out;
}

export function WhatIfPanel({ baseEstimate, baseInput }: Props) {
  const initialDraft = useMemo(
    () => draftFromInput(baseInput, baseEstimate),
    [baseInput, baseEstimate],
  );

  const [draft, setDraft] = useState<Draft>(initialDraft);
  const [autoMode, setAutoMode] = useState(true);
  // Результат последнего what-if пересчёта (локальный, не трогает страницу).
  const [whatIfEstimate, setWhatIfEstimate] = useState<AggregatedEstimate | null>(null);

  const mutation = useEstimateMutation();

  // Сброс при смене baseline (новая оценка из формы / restore по ?id=).
  useEffect(() => {
    setDraft(initialDraft);
    setWhatIfEstimate(null);
  }, [initialDraft]);

  const baseKey = useMemo(() => draftKey(initialDraft), [initialDraft]);
  const currentKey = draftKey(draft);
  const isDirty = currentKey !== baseKey;

  const totalFloors = baseEstimate.total_floors ?? baseInput.total_floors ?? null;
  const floorMax = totalFloors && totalFloors > 0 ? totalFloors : 100;

  // Ключ последнего ОТПРАВЛЕННОГО драфта — чтобы не дёргать бэкенд на тех же значениях.
  const lastSentKeyRef = useRef<string>(baseKey);
  // #770 finding #27: монотонный счётчик запросов — фильтрует out-of-order ответы
  // (медленный старый пересчёт мог перетереть свежий результат).
  const reqSeqRef = useRef(0);
  useEffect(() => {
    lastSentKeyRef.current = baseKey;
  }, [baseKey]);

  const recompute = useCallback(
    (d: Draft) => {
      const key = draftKey(d);
      if (key === lastSentKeyRef.current) return; // ничего не изменилось
      lastSentKeyRef.current = key;
      const seq = ++reqSeqRef.current;
      mutation.mutate(applyDraft(baseInput, d), {
        onSuccess: (est) => {
          // Применяем только результат последнего отправленного пересчёта.
          if (seq === reqSeqRef.current) setWhatIfEstimate(est);
        },
      });
    },
    [baseInput, mutation],
  );

  // Debounced auto-recompute — только когда autoMode и draft реально отличается.
  useEffect(() => {
    if (!autoMode) return;
    if (currentKey === lastSentKeyRef.current) return;
    const t = setTimeout(() => recompute(draft), DEBOUNCE_MS);
    return () => clearTimeout(t);
    // currentKey покрывает все поля draft; recompute стабилен по baseInput.
  }, [autoMode, currentKey, draft, recompute]);

  function reset() {
    setDraft(initialDraft);
    setWhatIfEstimate(null);
    lastSentKeyRef.current = baseKey;
  }

  const isPending = mutation.isPending;
  // Активный результат для дельты: what-if если он отражает текущий драфт.
  const shownEstimate =
    isDirty && whatIfEstimate ? whatIfEstimate : null;
  const basePrice = headlinePrice(baseEstimate);
  const newPrice = shownEstimate ? headlinePrice(shownEstimate) : null;
  const delta = newPrice !== null ? newPrice - basePrice : null;
  const deltaPct = delta !== null && basePrice > 0 ? (delta / basePrice) * 100 : null;

  function patch(p: Partial<Draft>) {
    setDraft((s) => ({ ...s, ...p }));
  }

  return (
    <article className="card whatif-card">
      <div className="whatif-head">
        <div>
          <div className="section-kicker">Интерактив · Что-если</div>
          <h3 className="whatif-title">Поменяйте параметры — оценка пересчитается</h3>
        </div>
        <label className="whatif-auto" title="Автоматически пересчитывать после паузы">
          <input
            type="checkbox"
            checked={autoMode}
            onChange={(e) => setAutoMode(e.target.checked)}
          />
          <span>Авто-пересчёт</span>
        </label>
      </div>

      <div className="whatif-body">
        {/* Состояние ремонта — segmented */}
        <div className="whatif-field">
          <span className="whatif-label">Состояние ремонта</span>
          <div className="whatif-segmented" role="group" aria-label="Состояние ремонта">
            {REPAIR_OPTIONS.map((opt) => (
              <button
                key={opt.value}
                type="button"
                className={`whatif-seg${draft.repair_state === opt.value ? " is-active" : ""}`}
                aria-pressed={draft.repair_state === opt.value}
                onClick={() => patch({ repair_state: opt.value })}
              >
                {opt.label}
              </button>
            ))}
          </div>
        </div>

        <div className="whatif-row">
          {/* Этаж — stepper + slider */}
          <div className="whatif-field">
            <span className="whatif-label">
              Этаж{" "}
              <span className="whatif-hint">
                {draft.floor ?? "—"}
                {totalFloors ? ` / ${totalFloors}` : ""}
              </span>
            </span>
            <div className="whatif-stepper">
              <button
                type="button"
                className="whatif-step-btn"
                aria-label="Этаж ниже"
                disabled={(draft.floor ?? 1) <= 1}
                onClick={() => patch({ floor: Math.max(1, (draft.floor ?? 1) - 1) })}
              >
                −
              </button>
              <input
                className="whatif-slider"
                type="range"
                min={1}
                max={floorMax}
                value={draft.floor ?? 1}
                onChange={(e) => patch({ floor: Number(e.target.value) })}
                aria-label="Этаж"
              />
              <button
                type="button"
                className="whatif-step-btn"
                aria-label="Этаж выше"
                disabled={(draft.floor ?? 1) >= floorMax}
                onClick={() => patch({ floor: Math.min(floorMax, (draft.floor ?? 1) + 1) })}
              >
                +
              </button>
            </div>
          </div>

          {/* Площадь — numeric ± */}
          <div className="whatif-field">
            <span className="whatif-label">
              Площадь <span className="whatif-hint">м²</span>
            </span>
            <div className="whatif-stepper">
              <button
                type="button"
                className="whatif-step-btn"
                aria-label="Меньше площадь"
                disabled={draft.area_m2 <= 11}
                onClick={() =>
                  patch({ area_m2: Math.max(11, Math.round((draft.area_m2 - 1) * 10) / 10) })
                }
              >
                −
              </button>
              <input
                className="control mono whatif-num"
                type="number"
                step="0.5"
                min={11}
                max={499}
                value={draft.area_m2}
                onChange={(e) => {
                  const v = Number(e.target.value);
                  if (!Number.isNaN(v)) patch({ area_m2: v });
                }}
                aria-label="Площадь м²"
              />
              <button
                type="button"
                className="whatif-step-btn"
                aria-label="Больше площадь"
                disabled={draft.area_m2 >= 499}
                onClick={() =>
                  patch({ area_m2: Math.min(499, Math.round((draft.area_m2 + 1) * 10) / 10) })
                }
              >
                +
              </button>
            </div>
          </div>
        </div>

        {/* Балкон toggle */}
        <label className="whatif-balcony">
          <input
            type="checkbox"
            checked={draft.has_balcony}
            onChange={(e) => patch({ has_balcony: e.target.checked })}
          />
          <span>Есть балкон / лоджия</span>
        </label>
      </div>

      <div className="whatif-foot">
        <div className="whatif-result" aria-live="polite">
          {isPending ? (
            <span className="whatif-loading">
              <svg
                width="14"
                height="14"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                style={{ animation: "ti-spin 1s linear infinite" }}
              >
                <path d="M21 12a9 9 0 1 1-6.219-8.56" />
              </svg>
              Пересчитываем…
            </span>
          ) : delta !== null && newPrice !== null ? (
            <>
              <span
                className={`whatif-delta${delta > 0 ? " up" : delta < 0 ? " down" : ""}`}
                title="Пересчёт ходит к источникам заново — дельта включает естественный разброс свежих объявлений, а не только эффект изменённого параметра."
              >
                {formatDeltaMln(delta)}
                {deltaPct !== null && Math.abs(deltaPct) >= 0.1
                  ? ` (${delta >= 0 ? "+" : "−"}${Math.abs(deltaPct).toFixed(1)}%)`
                  : ""}
              </span>
              <span className="whatif-newprice mono">
                новая оценка {formatMln(newPrice)} ₽
              </span>
            </>
          ) : (
            <span className="whatif-baseline mono">
              {basePrice > 0 ? `исходная оценка ${formatMln(basePrice)} ₽` : "исходная оценка —"}
            </span>
          )}
        </div>

        <div className="whatif-actions">
          {!autoMode && (
            <button
              type="button"
              className="btn btn-primary whatif-recalc"
              disabled={!isDirty || isPending}
              style={{ opacity: !isDirty || isPending ? 0.55 : 1 }}
              onClick={() => recompute(draft)}
            >
              Пересчитать
            </button>
          )}
          <button
            type="button"
            className="btn btn-ghost"
            disabled={!isDirty && whatIfEstimate === null}
            onClick={reset}
          >
            Сбросить
          </button>
        </div>
      </div>

      {mutation.error && (
        <div className="whatif-error">{mutation.error.message}</div>
      )}
    </article>
  );
}
