"use client";

/**
 * PticaReports — ПТИЦА «Отчёты» tab (PR#3). Dark-styled export cockpit that
 * REUSES the real export infrastructure rather than faking downloads:
 *
 *   • PDF снимок  — GET /api/v1/parcels/{cad}/snapshot.pdf (same endpoint as
 *     analysis/ExportButtons → blob → triggerDownload).
 *   • CSV сырьё   — client-side CSV generation from the analyze response
 *     (replicating ExportButtons' buildCsvRows / escapeCsvCell logic; no
 *     backend endpoint, no hardcoded URL).
 *   • §22 .docx / .pptx — GET /api/v1/parcels/{cad}/forecast/export?format=…
 *     (same endpoint as ForecastExportButtons). Gated on the async forecast
 *     being ready (useParcelForecastQuery): until then the cards are disabled
 *     with an honest «готовится» tag.
 *
 * Full-report DOCX (#2259 R2 PR-F) — REAL: GET /report/download?format=docx.
 * One report build produces BOTH pdf + docx, so the DOCX card shares the SAME
 * useFullReport(cad) run as the full-report PDF card (enqueue → poll → download)
 * — clicking either kicks the same job; only the final download format differs
 * (remembered by the hook via pendingFormatRef). Legacy runs (built before PR-F)
 * carry no docx_path → the hook HEAD-preflights the docx URL and, on 404, shows
 * «Пересоберите отчёт» instead of silently downloading an HTML error page.
 *
 * Full-report PPTX (the prototype's presentation card) has NO backend endpoint —
 * the only PowerPoint export the backend ships is the §22 forecast above. So that
 * card renders DISABLED with a «скоро» tag (honest — we never trigger a 404).
 *
 * The «Состав отчёта» list is a visual checklist of the PDF snapshot's sections
 * (matches the prototype TOC); the PDF snapshot is the real multi-section
 * deliverable behind it.
 */

import { useState } from "react";
import { FileText, Download, Presentation, FileType, Lock } from "lucide-react";

import { API_BASE_URL } from "@/lib/api";
import { triggerDownload } from "@/lib/download";
import { useParcelForecastQuery } from "@/lib/site-finder-api";
import {
  useFullReport,
  formatElapsed,
  readyReportLabel,
  readyDocxLabel,
} from "@/hooks/useFullReport";
import type { ParcelAnalysis } from "@/types/site-finder";
import { StatusRow } from "@/components/site-finder/ptica/drawers/DrawerPrimitives";
import styles from "@/app/site-finder/analysis/[cad]/ptica/ptica.module.css";

interface Props {
  cad: string;
  analysis: ParcelAnalysis;
}

// ── CSV generation (replicates analysis/ExportButtons row + escape logic) ─────

function buildCsvRows(a: ParcelAnalysis): string[][] {
  return [
    ["Поле", "Значение"],
    ["Кадастровый номер", a.cad_num],
    ["Балл", String(a.score)],
    ["Оценка", a.score_label ?? ""],
    ["Вердикт МКД", a.gate_verdict?.verdict_label ?? ""],
    ["Район", a.district?.district_name ?? ""],
    [
      "Медиана ₽/м²",
      a.district?.median_price_per_m2
        ? String(a.district.median_price_per_m2)
        : "",
    ],
    [
      "Скорость продаж",
      a.velocity?.velocity_data_available !== false &&
      a.velocity?.velocity_score != null
        ? String(a.velocity.velocity_score)
        : "",
    ],
    [
      "Пайплайн 24 мес (кв.)",
      a.pipeline_24mo?.flats_total != null
        ? String(a.pipeline_24mo.flats_total)
        : "",
    ],
    [
      "Достоверность",
      a.confidence != null ? String(a.confidence) : (a.confidence_label ?? ""),
    ],
    ["POI (кол-во)", String(a.poi_count)],
    ["Конкурентов", String(a.competitors.length)],
  ];
}

// CSV-injection mitigation (OWASP / CWE-1236) — same guard as ExportButtons.
function escapeCsvCell(cell: string): string {
  let safe = cell;
  if (/^[=+\-@\t\r]/.test(safe)) {
    safe = "'" + safe;
  }
  const needsQuotes = /[",\n\r]/.test(safe);
  if (needsQuotes) {
    return `"${safe.replace(/"/g, '""')}"`;
  }
  return safe;
}

function generateCsvBlob(rows: string[][]): Blob {
  const csvContent = rows
    .map((row) => row.map(escapeCsvCell).join(","))
    .join("\r\n");
  // UTF-8 BOM → Excel-friendly (ui-microcopy export rule).
  return new Blob(["﻿" + csvContent], { type: "text/csv;charset=utf-8" });
}

// Cadastral numbers contain ":" — illegal/awkward in filenames on some OSes.
function sanitizeCad(cad: string): string {
  return cad.replace(/:/g, "_");
}

// ── Report-section checklist (mirrors the PDF snapshot's TOC) ─────────────────

interface ReportSection {
  label: string;
  eyebrow: string;
}

const REPORT_SECTIONS: ReportSection[] = [
  { label: "Паспорт участка", eyebrow: "PASSPORT" },
  { label: "Градостроительный потенциал", eyebrow: "BUILDABILITY" },
  { label: "Инженерная обеспеченность", eyebrow: "UTILITIES" },
  { label: "Рынок и конкуренты", eyebrow: "MARKET" },
  { label: "Прогноз §22", eyebrow: "FORECAST" },
  { label: "Финансовая модель", eyebrow: "FINANCE" },
];

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

type DownloadKind = "pdf" | "csv" | "forecast-docx" | "forecast-pptx";

export function PticaReports({ cad, analysis }: Props) {
  const [busy, setBusy] = useState<DownloadKind | null>(null);
  const [error, setError] = useState<string | null>(null);

  const { data: forecastData } = useParcelForecastQuery(cad);
  const forecastReady = forecastData?.status === "ready";

  // Полный PDF-отчёт (#2259 PR-E) — общий хук enqueue → poll → download.
  const fullReport = useFullReport(cad);

  async function handlePdf() {
    setBusy("pdf");
    setError(null);
    try {
      const res = await fetch(
        `${API_BASE_URL}/api/v1/parcels/${encodeURIComponent(
          cad,
        )}/snapshot.pdf`,
      );
      if (!res.ok) {
        throw new Error(`Ошибка сервера ${res.status}`);
      }
      const blob = await res.blob();
      triggerDownload(blob, `gendesign_${sanitizeCad(cad)}.pdf`);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Ошибка загрузки PDF");
    } finally {
      setBusy(null);
    }
  }

  function handleCsv() {
    setBusy("csv");
    setError(null);
    try {
      const rows = buildCsvRows(analysis);
      triggerDownload(
        generateCsvBlob(rows),
        `gendesign_${sanitizeCad(cad)}.csv`,
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : "Ошибка генерации CSV");
    } finally {
      setBusy(null);
    }
  }

  async function handleForecastExport(format: "docx" | "pptx") {
    const kind: DownloadKind =
      format === "docx" ? "forecast-docx" : "forecast-pptx";
    setBusy(kind);
    setError(null);
    try {
      const res = await fetch(
        `${API_BASE_URL}/api/v1/parcels/${encodeURIComponent(
          cad,
        )}/forecast/export?format=${format}`,
      );
      if (!res.ok) {
        setError(
          res.status === 404
            ? "Прогноз §22 ещё не готов"
            : "Не удалось получить отчёт",
        );
        return;
      }
      const blob = await res.blob();
      triggerDownload(blob, `gendesign_forecast_${sanitizeCad(cad)}.${format}`);
    } catch {
      setError("Не удалось получить отчёт");
    } finally {
      setBusy(null);
    }
  }

  return (
    <div className={styles.reportsRoot}>
      <div className={styles.viewHead}>
        <h2>
          Отчёты
          <span className={styles.viewSub}>экспорт и генерация · EXPORT</span>
        </h2>
      </div>

      <div className={styles.reportGrid}>
        {/* ── Export-format cards ───────────────────────────────────────── */}
        <div className={styles.panel}>
          <div className={styles.cardHead}>
            <h3 className={styles.cardTitle}>
              Экспорт <span className={styles.cardTitleSub}>FORMATS</span>
            </h3>
          </div>

          <div className={styles.exportGrid}>
            {/* PDF snapshot — REAL (/snapshot.pdf) */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={() => void handlePdf()}
              disabled={busy !== null}
              aria-label="Скачать снимок отчёта в формате PDF"
            >
              <span className={`${styles.fmt} ${styles.fmtPdf}`}>PDF</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {busy === "pdf" ? "Готовим…" : "Снимок отчёта"}
                </span>
                <span className={styles.exportDesc}>Все секции · PDF</span>
              </span>
              <FileText
                size={16}
                strokeWidth={1.5}
                className={styles.exportIco}
              />
            </button>

            {/* CSV — REAL (client-side) */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={handleCsv}
              disabled={busy !== null}
              aria-label="Скачать сырьё в формате CSV"
            >
              <span className={`${styles.fmt} ${styles.fmtCsv}`}>CSV</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {busy === "csv" ? "Генерация…" : "Сырьё"}
                </span>
                <span className={styles.exportDesc}>Метрики анализа</span>
              </span>
              <Download
                size={16}
                strokeWidth={1.5}
                className={styles.exportIco}
              />
            </button>

            {/* §22 forecast DOCX — REAL, gated on forecast ready */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={() => void handleForecastExport("docx")}
              disabled={busy !== null || !forecastReady}
              aria-label="Скачать прогноз §22 в формате Word"
            >
              <span className={`${styles.fmt} ${styles.fmtDocx}`}>DOCX</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {busy === "forecast-docx" ? "Готовим…" : "Прогноз §22"}
                  {!forecastReady && (
                    <span className={styles.exportTag}>готовится</span>
                  )}
                </span>
                <span className={styles.exportDesc}>Word · сценарии</span>
              </span>
              <FileType
                size={16}
                strokeWidth={1.5}
                className={styles.exportIco}
              />
            </button>

            {/* §22 forecast PPTX — REAL, gated on forecast ready */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={() => void handleForecastExport("pptx")}
              disabled={busy !== null || !forecastReady}
              aria-label="Скачать прогноз §22 в формате презентации"
            >
              <span className={`${styles.fmt} ${styles.fmtPptx}`}>PPTX</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {busy === "forecast-pptx" ? "Готовим…" : "Прогноз §22"}
                  {!forecastReady && (
                    <span className={styles.exportTag}>готовится</span>
                  )}
                </span>
                <span className={styles.exportDesc}>Для инвесткомитета</span>
              </span>
              <Presentation
                size={16}
                strokeWidth={1.5}
                className={styles.exportIco}
              />
            </button>

            {/* Full-report PDF — REAL async job (#2259 PR-E): enqueue → poll → download */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={() =>
                fullReport.uiState === "ready"
                  ? fullReport.download()
                  : fullReport.start()
              }
              disabled={fullReport.uiState === "building"}
              aria-label={
                fullReport.uiState === "ready"
                  ? "Скачать полный отчёт в формате PDF"
                  : "Собрать и скачать полный отчёт в формате PDF"
              }
            >
              <span className={`${styles.fmt} ${styles.fmtPdf}`}>PDF</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {fullReport.uiState === "building"
                    ? `Готовится… ${formatElapsed(fullReport.elapsedMs)}`
                    : fullReport.uiState === "ready"
                      ? readyReportLabel(fullReport.reportGeneratedAt)
                      : "Полный отчёт"}
                </span>
                <span className={styles.exportDesc}>
                  {fullReport.uiState === "timeout"
                    ? "Сборка затянулась — попробуйте позже"
                    : fullReport.uiState === "error"
                      ? "Не удалось поставить сборку — повторите"
                      : "Все секции · PDF"}
                </span>
              </span>
              {fullReport.uiState === "building" ? (
                <span
                  className={styles.pendingPulse}
                  style={{ width: 16, height: 16, borderWidth: 2 }}
                  aria-hidden="true"
                />
              ) : (
                <FileText
                  size={16}
                  strokeWidth={1.5}
                  className={styles.exportIco}
                />
              )}
            </button>

            {/* Full-report DOCX — REAL (#2259 R2 PR-F): same run as PDF card,
                final download ?format=docx. Building-спиннер общий на прогон. */}
            <button
              type="button"
              className={styles.exportCard}
              onClick={() =>
                fullReport.uiState === "ready"
                  ? fullReport.download("docx")
                  : fullReport.start("docx")
              }
              disabled={fullReport.uiState === "building"}
              aria-label={
                fullReport.uiState === "ready"
                  ? "Скачать полный отчёт в формате Word"
                  : "Собрать и скачать полный отчёт в формате Word"
              }
            >
              <span className={`${styles.fmt} ${styles.fmtDocx}`}>DOCX</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  {fullReport.uiState === "building"
                    ? `Готовится… ${formatElapsed(fullReport.elapsedMs)}`
                    : fullReport.uiState === "ready"
                      ? readyDocxLabel(fullReport.reportGeneratedAt)
                      : "Полный отчёт"}
                </span>
                <span className={styles.exportDesc}>
                  {fullReport.uiState === "timeout"
                    ? "Сборка затянулась — попробуйте позже"
                    : fullReport.uiState === "error"
                      ? "Не удалось поставить сборку — повторите"
                      : "Все секции · Word"}
                </span>
              </span>
              {fullReport.uiState === "building" ? (
                <span
                  className={styles.pendingPulse}
                  style={{ width: 16, height: 16, borderWidth: 2 }}
                  aria-hidden="true"
                />
              ) : (
                <FileType
                  size={16}
                  strokeWidth={1.5}
                  className={styles.exportIco}
                />
              )}
            </button>

            {/* Full-report PPTX — NO endpoint → honest disabled «скоро» */}
            <div
              className={`${styles.exportCard} ${styles.exportCardDisabled}`}
              aria-disabled="true"
            >
              <span className={`${styles.fmt} ${styles.fmtMuted}`}>PPTX</span>
              <span className={styles.exportMeta}>
                <span className={styles.exportTitle}>
                  Презентация
                  <span className={styles.exportTagSoon}>скоро</span>
                </span>
                <span className={styles.exportDesc}>Полный отчёт · слайды</span>
              </span>
              <Lock size={16} strokeWidth={1.5} className={styles.exportIco} />
            </div>
          </div>

          {error && (
            <p className={styles.reportError} role="alert">
              {error}
            </p>
          )}

          {/* Легаси-раны без docx (собраны до PR-F) → download?format=docx = 404.
              Хук ловит это HEAD-preflight'ом и просит пересобрать отчёт. */}
          {fullReport.downloadError && (
            <p className={styles.reportError} role="alert">
              {fullReport.downloadError}
            </p>
          )}

          {/* ── Параметры — что войдёт в сгенерированный отчёт ─────────────── */}
          <hr className={styles.overlayDivider} />
          <h3 className={styles.cardTitle}>
            Параметры <span className={styles.cardTitleSub}>OPTIONS</span>
          </h3>
          <StatusRow label="Включить карту и слои" state="Да" tone="ok" />
          <StatusRow label="Включить финмодель" state="Да" tone="ok" />
          <StatusRow
            label="Включить прогноз §22"
            state={forecastReady ? "Включён" : "Готовится"}
            tone={forecastReady ? "ok" : "warn"}
          />
        </div>

        {/* ── Report-section checklist ──────────────────────────────────── */}
        <div className={styles.panel}>
          <div className={styles.cardHead}>
            <h3 className={styles.cardTitle}>
              Состав отчёта{" "}
              <span className={styles.cardTitleSub}>SECTIONS</span>
            </h3>
          </div>

          <div className={styles.tocList}>
            {REPORT_SECTIONS.map((section, i) => (
              <div key={section.eyebrow} className={styles.tocItem}>
                <span className={styles.tocIndex}>
                  {String(i + 1).padStart(2, "0")}
                </span>
                <span className={styles.tocLabel}>{section.label}</span>
                <span className={styles.tocEyebrow}>{section.eyebrow}</span>
              </div>
            ))}
          </div>

          <div className={styles.sourceLine}>
            <span>GENDESIGN · PDF снимок</span>
            <span className="mono">{cad}</span>
          </div>
        </div>
      </div>
    </div>
  );
}
