"use client";

/**
 * HeroTransparency — блок «доверие + действия» в HEADER результата трейд-ин.
 *
 * Web-преимущества над статичным PDF:
 *   1. «Как рассчитано» — collapsible (details/summary): уровень аналогов
 *      (парсится из confidence_explanation), n_analogs, человекочитаемый band
 *      достоверности и полный текст объяснения. Доверие appraiser-grade, on demand.
 *   2. Свежесть данных — строка «Данные актуальны на …» из last_scraped_at либо
 *      now − data_freshness_minutes. Подчёркивает «это не устаревший PDF».
 *   3. «Скачать PDF-отчёт» — ссылка на brand-aware endpoint (тот же, что в OfferCard).
 *   4. Форма заявки «Оставить заявку на трейд-ин» — телефон + явное согласие
 *      ФЗ-152 → POST /api/v1/trade-in/lead (issue #2377, backend #2376/PR #2390).
 *      Заменяет прежний mailto-стаб (граничный кейс без backend'а, PR #689) —
 *      теперь доступна всегда, без env-гейтинга по контакт-email.
 *
 * Тема — через brand-CSS-vars (--accent…), responsive, всё graceful при null-полях.
 */

import { useState, useEffect } from "react";
import type { AggregatedEstimate, AnalogTier, ConfidenceLevel } from "@/types/trade-in";
import { API_BASE_URL } from "@/lib/api";
import { useCreateLeadMutation } from "@/lib/trade-in-api";

interface Props {
  estimate: AggregatedEstimate;
  /** Активный brand slug (useActiveBrandSlug) — для brand-aware PDF endpoint. */
  brandSlug: string | null;
  /** Имя бренда (Brand.name) — подпись в заголовке формы заявки. null → generic. */
  brandName: string | null;
}

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

/**
 * Структурный маппинг analog_tier → читаемый лейбл.
 * Используется ПРЕДПОЧТИТЕЛЬНО если бэкенд уже отдаёт поле.
 */
const ANALOG_TIER_LABELS: Record<AnalogTier, string> = {
  same_building: "по аналогам того же дома",
  micro_radius: "по ближайшему окружению ≤500 м",
  district: "по аналогам района",
  city: "по аналогам города (широкий радиус)",
};

/**
 * Маппинг address_precision → читаемый лейбл для коллапсибл-деталей.
 */
const PRECISION_LABELS: Record<string, string> = {
  house: "до дома",
  street: "до улицы",
  approximate: "приблизительно",
};

/**
 * Маска телефона для формы заявки — зеркалит _PHONE_PATTERN бэкенда
 * (tradein-mvp/backend/app/api/v1/lead.py): опциональный "+", цифры/пробелы/
 * скобки/дефисы/точки, 5-32 символа. Клиентская проверка даёт мгновенный
 * feedback до сетевого 422 (полная E.164-нормализация — вне scope MVP).
 */
const PHONE_PATTERN = /^[+]?[\d\s().-]{5,32}$/;
function isValidPhone(v: string): boolean {
  return PHONE_PATTERN.test(v.trim());
}

/**
 * LEGACY fallback: эвристика уровня сопоставимых объектов из confidence_explanation.
 * Бэкенд кладёт туда формулировку якорного tier'а; вытаскиваем человекочитаемую.
 * Null → ничего не показываем (graceful).
 *
 * Используется только если бэкенд ещё не отдаёт структурного analog_tier —
 * предпочитай resolveCompsTier() которая сначала смотрит на analog_tier.
 */
function compsTier(explanation: string | null): string | null {
  // FIXME: backend should expose structured comps_tier (#695 follow-up).
  // AggregatedEstimate не отдаёт структурного tier-поля для anchor-уровня
  // (только AnalogLot.tier для отдельных rosreestr-сделок), поэтому уровень
  // приходится извлекать substring-эвристикой из прозы confidence_explanation.
  // Хрупко к переформулировке бэкенда — оставлено как fallback до появления поля.
  if (!explanation) return null;
  const t = explanation.toLowerCase();
  if (t.includes("тот же дом") || t.includes("того же дома") || t.includes("этом же доме"))
    return "по аналогам того же дома";
  if (t.includes("≤500") || t.includes("<=500") || t.includes("500 м") || t.includes("окружени"))
    return "по окружению ≤500 м";
  if (t.includes("район") || t.includes("микрорайон")) return "по аналогам района";
  if (t.includes("город")) return "по аналогам города";
  return null;
}

/**
 * Предпочитает структурное поле analog_tier (если задано бэкендом).
 * Если absent/null — graceful fallback на compsTier() эвристику.
 */
function resolveCompsTier(estimate: AggregatedEstimate): string | null {
  if (estimate.analog_tier) {
    return ANALOG_TIER_LABELS[estimate.analog_tier] ?? null;
  }
  return compsTier(estimate.confidence_explanation);
}

/**
 * «27 мая 2026, 14:30» — timeZone: "UTC" фиксирует вывод одинаково на SSR (Node UTC)
 * и клиенте (любой TZ). Иначе «12:00» на сервере → «15:00» у клиента в Москве → React #418.
 */
function formatRuDateTime(d: Date): string {
  return new Intl.DateTimeFormat("ru-RU", {
    day: "numeric",
    month: "long",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
    timeZone: "UTC",
  }).format(d);
}

/**
 * Момент актуальности данных из last_scraped_at (ISO).
 * Возвращает Date или null. Не использует Date.now() — безопасна для SSR.
 */
function freshnessFromScraped(estimate: AggregatedEstimate): Date | null {
  if (estimate.last_scraped_at) {
    const d = new Date(estimate.last_scraped_at);
    if (!Number.isNaN(d.getTime())) return d;
  }
  return null;
}

export function HeroTransparency({ estimate, brandSlug, brandName }: Props) {
  // Defensive depth (audit #1871 P1.2): ghost-anchor guard, как в HeroSummary.
  // n_analogs=0 → отображаем «низкая достоверность», даже если контракт-drift
  // отдал confidence='high'. Caveat-текст — из confidence_explanation (backend).
  const effectiveConfidence: ConfidenceLevel =
    estimate.n_analogs === 0 ? "low" : estimate.confidence;
  const band = CONF_BAND[effectiveConfidence] ?? CONF_BAND.low;
  // Задача 1: предпочитаем структурный analog_tier, fallback на эвристику строки.
  const tier = resolveCompsTier(estimate);
  // Задача 2: точность адреса в деталях (если задана).
  const precisionLabel =
    estimate.address_precision != null
      ? (PRECISION_LABELS[estimate.address_precision] ?? null)
      : null;
  // Предупреждение при low-confidence + приблизительном адресе.
  const showPrecisionWarning =
    effectiveConfidence === "low" && estimate.address_precision === "approximate";

  // SSR-safe: берём last_scraped_at (статичная ISO строка — нет мismatch).
  // Если его нет, fallback на data_freshness_minutes через Date.now() —
  // но Date.now() нельзя в render (SSR/client mismatch → React #418), поэтому
  // вычисляем ТОЛЬКО на клиенте через useEffect.
  const scrapedFresh = freshnessFromScraped(estimate);
  const [fallbackFresh, setFallbackFresh] = useState<Date | null>(null);
  useEffect(() => {
    if (scrapedFresh !== null) return; // last_scraped_at уже есть — fallback не нужен
    if (
      typeof estimate.data_freshness_minutes === "number" &&
      estimate.data_freshness_minutes >= 0
    ) {
      setFallbackFresh(new Date(Date.now() - estimate.data_freshness_minutes * 60_000));
    }
  }, [estimate.data_freshness_minutes, scrapedFresh]);
  const fresh = scrapedFresh ?? fallbackFresh;

  // PDF endpoint (api/v1/trade_in.py) уже honor'ит ?brand= для white-label —
  // тот же паттерн, что в OfferCard, поэтому консистентно.
  const pdfQuery = brandSlug ? `?brand=${encodeURIComponent(brandSlug)}` : "";
  const pdfHref = `${API_BASE_URL}/api/v1/trade-in/estimate/${estimate.estimate_id}/pdf${pdfQuery}`;

  // ── Форма заявки (issue #2377) — телефон + согласие ФЗ-152 → POST /lead. ──
  // Controlled inputs (useState), без useEffect для HTTP — TanStack Query mutation.
  const [phone, setPhone] = useState("");
  const [consent, setConsent] = useState(false);
  const [leadTouched, setLeadTouched] = useState(false);
  const leadMutation = useCreateLeadMutation();
  const phoneInvalid = leadTouched && !isValidPhone(phone);
  const leadApiError =
    typeof leadMutation.error?.message === "string" && leadMutation.error.message
      ? leadMutation.error.message
      : leadMutation.isError
        ? "Не удалось отправить заявку, попробуйте ещё раз"
        : null;
  const canSubmitLead = isValidPhone(phone) && consent && !leadMutation.isPending;

  function handleLeadSubmit(e: React.FormEvent) {
    e.preventDefault();
    setLeadTouched(true);
    if (!isValidPhone(phone) || !consent || leadMutation.isPending) return;
    leadMutation.mutate({
      phone: phone.trim(),
      consent: true,
      estimate_id: estimate.estimate_id,
      source: "result",
    });
  }

  return (
    <div className="hero-trust">
      <div className="hero-lead">
        {leadMutation.isSuccess ? (
          <p className="hero-lead-success" role="status">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
              <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
              <polyline points="22 4 12 14.01 9 11.01" />
            </svg>
            Заявка принята, мы свяжемся с вами
          </p>
        ) : (
          <form className="hero-lead-form" onSubmit={handleLeadSubmit} noValidate>
            <div className="hero-lead-head">
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <path d="M4 4h16v12H5.17L4 17.17V4z" />
                <line x1="8" y1="9" x2="16" y2="9" />
                <line x1="8" y1="12.5" x2="13" y2="12.5" />
              </svg>
              <span>Оставить заявку на трейд-ин{brandName ? ` · ${brandName}` : ""}</span>
            </div>
            <div className="hero-lead-row">
              <input
                className="control"
                type="tel"
                inputMode="tel"
                autoComplete="tel"
                placeholder="+7 900 000-00-00"
                aria-label="Телефон для связи"
                aria-invalid={phoneInvalid ? true : undefined}
                value={phone}
                onChange={(e) => setPhone(e.target.value)}
                disabled={leadMutation.isPending}
              />
              <button
                type="submit"
                className="btn btn-accent hero-lead-submit"
                disabled={leadMutation.isPending}
                aria-disabled={canSubmitLead ? undefined : true}
                style={{ opacity: canSubmitLead ? 1 : 0.55 }}
              >
                {leadMutation.isPending ? "Отправляем…" : "Оставить заявку"}
              </button>
            </div>
            <label className="hero-lead-consent">
              <input
                type="checkbox"
                checked={consent}
                onChange={(e) => setConsent(e.target.checked)}
                disabled={leadMutation.isPending}
              />
              <span>
                Согласен(-на) на обработку персональных данных в соответствии с Федеральным
                законом «О персональных данных» № 152-ФЗ
              </span>
            </label>
            {phoneInvalid && (
              <p className="hero-lead-error">
                Введите телефон (5–32 символа: цифры, +, пробелы, скобки, дефис)
              </p>
            )}
            {leadApiError && <p className="hero-lead-error">{leadApiError}</p>}
          </form>
        )}
      </div>

      <div className="hero-trust-actions">
        <a className="btn btn-ghost hero-trust-pdf" href={pdfHref} target="_blank" rel="noopener noreferrer">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
            <polyline points="14 2 14 8 20 8" />
            <line x1="12" y1="18" x2="12" y2="12" />
            <polyline points="9 15 12 18 15 15" />
          </svg>
          Скачать PDF-отчёт
        </a>
      </div>

      {fresh && (
        <p className="hero-trust-freshness">
          <span className="dot" aria-hidden="true" />
          Данные актуальны на <b>{formatRuDateTime(fresh)}</b>
        </p>
      )}

      <details className="hero-trust-how">
        <summary>
          <span className="how-title">Как рассчитано</span>
          <span className="how-band">{band}</span>
          <svg className="how-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polyline points="6 9 12 15 18 9" />
          </svg>
        </summary>
        <div className="how-body">
          <ul className="how-facts">
            {tier && (
              <li>
                <span className="k">Сопоставление</span>
                <span className="v">{tier}</span>
              </li>
            )}
            <li>
              <span className="k">Аналогов в выборке</span>
              <span className="v mono">{estimate.n_analogs}</span>
            </li>
            <li>
              <span className="k">Достоверность оценки</span>
              <span className="v">{band}</span>
            </li>
            {precisionLabel && (
              <li>
                <span className="k">Точность адреса</span>
                <span
                  className="v"
                  style={
                    showPrecisionWarning
                      ? { color: "var(--danger)", fontWeight: 600 }
                      : undefined
                  }
                >
                  {precisionLabel}
                  {showPrecisionWarning && (
                    <span
                      aria-label="Предупреждение: адрес определён приблизительно при низкой достоверности"
                      style={{ marginLeft: 6, display: "inline-flex", alignItems: "center", gap: 4 }}
                    >
                      <span
                        aria-hidden="true"
                        style={{
                          display: "inline-block",
                          width: 7,
                          height: 7,
                          borderRadius: "50%",
                          background: "var(--warn)",
                          verticalAlign: "middle",
                        }}
                      />
                      <span style={{ fontSize: 11, color: "var(--warn)", fontWeight: 600 }}>Приблизительно</span>
                    </span>
                  )}
                </span>
              </li>
            )}
          </ul>
          {estimate.confidence_explanation && !estimate.confidence_explanation.startsWith("address_not_geocoded") && (
            <p className="how-explanation">{estimate.confidence_explanation}</p>
          )}
        </div>
      </details>
    </div>
  );
}
