"use client";

/**
 * ExportButtons — PDF snapshot (B7) + frontend-side CSV generation.
 *
 * PDF: GET /api/v1/parcels/{cad}/snapshot.pdf → blob download.
 * CSV: client-side generation from analyze response fields.
 * Loading state, error toast via alert (no toast lib dep).
 */

import { useState } from "react";
import { Download, FileText, FileBarChart, FileType } from "lucide-react";
import { API_BASE_URL } from "@/lib/api";
import { triggerDownload } from "@/lib/download";
import {
  useFullReport,
  formatElapsed,
  readyReportLabel,
  readyDocxLabel,
} from "@/hooks/useFullReport";
import type { ParcelAnalyzeResponse, ParcelEgrn } from "@/lib/site-finder-api";

interface Props {
  cad: string;
  analyzeData?: ParcelAnalyzeResponse | null;
  /**
   * Adapted EGRN (frontend ParcelEgrn shape). Passed in by the parent
   * (Section1ParcelInfo) which runs `adaptEgrn` on `analyzeData.egrn` to
   * translate backend snake_case columns (permitted_use_text / land_category /
   * etc.) → frontend labels (vri / category / etc.). Without this, the CSV's
   * 9 ЕГРН columns rendered empty in prod (#1217).
   */
  egrn?: ParcelEgrn | null;
}

// ── CSV generation ────────────────────────────────────────────────────────────

function buildCsvRows(
  data: ParcelAnalyzeResponse,
  egrn: ParcelEgrn | null | undefined,
): string[][] {
  const rows: string[][] = [
    ["Поле", "Значение"],
    ["Кадастровый номер", data.cad_num],
    ["Балл", String(data.score)],
    ["Оценка", data.score_label ?? ""],
    ["Район", data.district?.district_name ?? ""],
    [
      "Медиана ₽/м²",
      data.district?.median_price_per_m2
        ? String(data.district.median_price_per_m2)
        : "",
    ],
    ["POI (кол-во)", String(data.poi_count)],
  ];

  if (egrn) {
    rows.push(
      ["Адрес", egrn.address],
      ["Площадь м²", Number.isFinite(egrn.area_m2) ? String(egrn.area_m2) : ""],
      ["ВРИ", egrn.vri],
      ["Категория", egrn.category],
      ["Форма собственности", egrn.owner_type],
      ["Обременения", egrn.encumbrance],
      ["Статус ЕГРН", egrn.status],
      ["Дата регистрации", egrn.registration_date ?? ""],
      ["Обновлено", egrn.last_updated ?? ""],
    );
  }

  return rows;
}

function escapeCsvCell(cell: string): string {
  // CSV-injection mitigation (OWASP / CWE-1236): cells starting with =, +, -, @,
  // tab, or CR are evaluated as formulas by Excel/Calc/Sheets. Prefix dangerous
  // starters with a leading apostrophe so the spreadsheet treats them as text.
  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");
  return new Blob(["﻿" + csvContent], { type: "text/csv;charset=utf-8" });
}

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

export function ExportButtons({ cad, analyzeData, egrn }: Props) {
  const [pdfLoading, setPdfLoading] = useState(false);
  const [csvLoading, setCsvLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

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

  async function handlePdfDownload() {
    setPdfLoading(true);
    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, `участок-${cad}.pdf`);
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Ошибка загрузки PDF";
      setError(msg);
    } finally {
      setPdfLoading(false);
    }
  }

  function handleCsvDownload() {
    setCsvLoading(true);
    setError(null);
    try {
      if (!analyzeData) {
        setError("Данные ещё не загружены");
        return;
      }
      const rows = buildCsvRows(analyzeData, egrn);
      const blob = generateCsvBlob(rows);
      triggerDownload(blob, `участок-${cad}.csv`);
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Ошибка генерации CSV";
      setError(msg);
    } finally {
      setCsvLoading(false);
    }
  }

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
        {/* PDF button — secondary (orange per design token) */}
        <button
          onClick={() => void handlePdfDownload()}
          disabled={pdfLoading}
          aria-label="Скачать снапшот PDF"
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            padding: "6px 12px",
            height: 32,
            background: pdfLoading ? "var(--bg-card-alt)" : "var(--accent-2)",
            color: pdfLoading ? "var(--fg-tertiary)" : "#fff",
            border: "none",
            borderRadius: 6,
            fontSize: 13,
            fontWeight: 500,
            cursor: pdfLoading ? "not-allowed" : "pointer",
            opacity: pdfLoading ? 0.6 : 1,
            transition: "opacity 150ms",
          }}
        >
          <FileText size={14} strokeWidth={1.5} />
          {pdfLoading ? "Загрузка..." : "Снапшот PDF"}
        </button>

        {/* CSV button — secondary (orange) */}
        <button
          onClick={handleCsvDownload}
          disabled={csvLoading || !analyzeData}
          aria-label="Скачать данные CSV"
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            padding: "6px 12px",
            height: 32,
            background:
              csvLoading || !analyzeData
                ? "var(--bg-card-alt)"
                : "var(--accent-2)",
            color: csvLoading || !analyzeData ? "var(--fg-tertiary)" : "#fff",
            border: "none",
            borderRadius: 6,
            fontSize: 13,
            fontWeight: 500,
            cursor: csvLoading || !analyzeData ? "not-allowed" : "pointer",
            opacity: csvLoading || !analyzeData ? 0.6 : 1,
            transition: "opacity 150ms",
          }}
        >
          <Download size={14} strokeWidth={1.5} />
          {csvLoading ? "Генерация..." : "Скачать CSV"}
        </button>

        {/* Full-report PDF — async job (#2259 PR-E): enqueue → poll → download */}
        <button
          onClick={() =>
            reportReady ? fullReport.download() : fullReport.start()
          }
          disabled={reportBuilding}
          aria-label={
            reportReady
              ? "Скачать полный отчёт PDF"
              : "Собрать и скачать полный отчёт PDF"
          }
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            padding: "6px 12px",
            height: 32,
            background: reportBuilding
              ? "var(--bg-card-alt)"
              : "var(--accent-2)",
            color: reportBuilding ? "var(--fg-tertiary)" : "#fff",
            border: "none",
            borderRadius: 6,
            fontSize: 13,
            fontWeight: 500,
            cursor: reportBuilding ? "not-allowed" : "pointer",
            opacity: reportBuilding ? 0.6 : 1,
            transition: "opacity 150ms",
          }}
        >
          <FileBarChart size={14} strokeWidth={1.5} />
          {reportBuilding
            ? `Готовится… ${formatElapsed(fullReport.elapsedMs)}`
            : reportReady
              ? readyReportLabel(fullReport.reportGeneratedAt)
              : "Полный отчёт (PDF)"}
        </button>

        {/*
          Full-report DOCX — вторичный компакт рядом с «Полный отчёт (PDF)».
          Тот же общий прогон useFullReport (один enqueue→poll даёт pdf+docx),
          финальный download в ?format=docx. Компактнее PDF-кнопки (иконка +
          «DOCX»), чтобы не перегружать ряд. Building/ready-состояние — общее с
          PDF-кнопкой (обе дизейблятся на сборке).
        */}
        <button
          onClick={() =>
            reportReady ? fullReport.download("docx") : fullReport.start("docx")
          }
          disabled={reportBuilding}
          aria-label={
            reportReady
              ? "Скачать полный отчёт Word"
              : "Собрать и скачать полный отчёт Word"
          }
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 6,
            padding: "6px 12px",
            height: 32,
            background: reportBuilding
              ? "var(--bg-card-alt)"
              : "var(--accent-2)",
            color: reportBuilding ? "var(--fg-tertiary)" : "#fff",
            border: "none",
            borderRadius: 6,
            fontSize: 13,
            fontWeight: 500,
            cursor: reportBuilding ? "not-allowed" : "pointer",
            opacity: reportBuilding ? 0.6 : 1,
            transition: "opacity 150ms",
          }}
        >
          <FileType size={14} strokeWidth={1.5} />
          {reportReady ? readyDocxLabel(fullReport.reportGeneratedAt) : "DOCX"}
        </button>
      </div>

      {/* Full-report timeout / enqueue-error note (contract has no "failed") */}
      {fullReport.uiState === "timeout" && (
        <p
          style={{ margin: 0, fontSize: 12, color: "var(--warn)" }}
          role="alert"
        >
          Сборка затянулась — попробуйте позже
        </p>
      )}
      {fullReport.uiState === "error" && (
        <p
          style={{ margin: 0, fontSize: 12, color: "var(--danger)" }}
          role="alert"
        >
          Не удалось поставить сборку отчёта — повторите
        </p>
      )}
      {/* Легаси-ран без docx (собран до PR-F) → download?format=docx = 404. */}
      {fullReport.downloadError && (
        <p
          style={{ margin: 0, fontSize: 12, color: "var(--danger)" }}
          role="alert"
        >
          {fullReport.downloadError}
        </p>
      )}

      {/* Error message */}
      {error && (
        <p
          style={{
            margin: 0,
            fontSize: 12,
            color: "var(--danger)",
          }}
          role="alert"
        >
          {error}
        </p>
      )}
    </div>
  );
}
