import { useEffect, useRef, useState, useCallback } from 'react';
import { useParams } from 'react-router-dom';
import * as pdfjsLib from 'pdfjs-dist';
// @ts-ignore
import pdfWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
import { ENDPOINTS } from '../../api/endpoints';
import { LOGO_URL } from '../../config/env';

pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker;

// ─── Types ───────────────────────────────────────────────────────────────────

interface InvoiceData {
  invoiceNo: string;
  invoiceDate: string;
  customerName?: string;
  grandTotal?: string | number;
  balanceAmount?: string | number;
  paymentStatus?: string;
}

// ─── Helpers ─────────────────────────────────────────────────────────────────

const fmtDate = (d: string) => {
  try {
    return new Date(d).toLocaleDateString('en-IN', {
      day: '2-digit',
      month: 'short',
      year: 'numeric',
    });
  } catch {
    return d;
  }
};

const fmtCurrency = (val: any) => {
  const num = Number(val);
  if (isNaN(num)) return '';
  return `₹${num.toLocaleString('en-IN')}`;
};

// ─── Main Component ───────────────────────────────────────────────────────────

export default function InvoicePreview() {
  const { token } = useParams<{ token: string }>();
  const [data, setData] = useState<InvoiceData | null>(null);
  const [pdfBlob, setPdfBlob] = useState<Blob | null>(null);
  const [pdfDoc, setPdfDoc] = useState<pdfjsLib.PDFDocumentProxy | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [downloading, setDownloading] = useState(false);
  const [scale, setScale] = useState<number>(1.2);

  const containerRef = useRef<HTMLDivElement>(null);
  const canvasRefs = useRef<(HTMLCanvasElement | null)[]>([]);

  // 1. Fetch metadata & PDF blob
  useEffect(() => {
    if (!token) return;
    setLoading(true);
    setError(null);

    let active = true;

    Promise.all([
      fetch(`/api/${ENDPOINTS.PUBLIC_INVOICE(token)}`).then(async (res) => {
        if (!res.ok) {
          const body = await res.json().catch(() => ({}));
          throw new Error(body.message || 'Invoice not found');
        }
        return res.json();
      }),
      fetch(`/api/${ENDPOINTS.PUBLIC_INVOICE_PDF(token)}`).then(async (res) => {
        if (!res.ok) {
          throw new Error('Failed to load invoice document');
        }
        return res.blob();
      }),
    ])
      .then(async ([invoiceData, blob]) => {
        if (!active) return;
        setData(invoiceData);
        setPdfBlob(blob);

        const arrayBuffer = await blob.arrayBuffer();
        const loadedPdf = await pdfjsLib.getDocument({
          data: arrayBuffer,
        }).promise;

        if (!active) return;
        setPdfDoc(loadedPdf);
      })
      .catch((e) => {
        if (!active) return;
        setError(e.message || 'Failed to load invoice');
      })
      .finally(() => {
        if (active) setLoading(false);
      });

    return () => {
      active = false;
    };
  }, [token]);

  // Adjust initial scale to fit screen comfortably on mobile or desktop
  useEffect(() => {
    if (!containerRef.current) return;
    const containerWidth = containerRef.current.clientWidth;
    if (containerWidth < 640) {
      // Mobile screen: scale to match container width with small padding
      const targetScale = (containerWidth - 24) / 595.28; // 595.28 is standard A4 pt width
      setScale(Math.max(targetScale, 0.5));
    } else {
      setScale(1.25);
    }
  }, [loading]);

  const activeRenderTasksRef = useRef<{ [key: number]: any }>({});

  // 2. Render PDF pages to canvases
  const renderPages = useCallback(async () => {
    if (!pdfDoc) return;

    for (let pageNum = 1; pageNum <= pdfDoc.numPages; pageNum++) {
      const canvas = canvasRefs.current[pageNum - 1];
      if (!canvas) continue;

      if (activeRenderTasksRef.current[pageNum]) {
        try {
          activeRenderTasksRef.current[pageNum].cancel();
        } catch {}
      }

      const page = await pdfDoc.getPage(pageNum);
      const dpr = Math.min(window.devicePixelRatio || 1, 2.5);
      const viewport = page.getViewport({ scale: scale * dpr });

      canvas.width = viewport.width;
      canvas.height = viewport.height;
      canvas.style.width = `${viewport.width / dpr}px`;
      canvas.style.height = `${viewport.height / dpr}px`;

      const ctx = canvas.getContext('2d');
      if (!ctx) continue;

      const renderTask = page.render({
        canvas,
        canvasContext: ctx,
        viewport,
      });
      activeRenderTasksRef.current[pageNum] = renderTask;

      try {
        await renderTask.promise;
      } catch (err: any) {
        if (err?.name !== 'RenderingCancelledException') {
          console.error(err);
        }
      }
    }
  }, [pdfDoc, scale]);

  useEffect(() => {
    renderPages();
  }, [renderPages]);

  // 3. Action Handlers
  const handleDownload = () => {
    if (!pdfBlob) return;
    setDownloading(true);
    try {
      const url = URL.createObjectURL(pdfBlob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${data?.invoiceNo ?? 'invoice'}.pdf`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    } finally {
      setTimeout(() => setDownloading(false), 800);
    }
  };

  const handlePrint = () => {
    if (!pdfBlob) return;
    const url = URL.createObjectURL(pdfBlob);
    const win = window.open(url, '_blank');
    if (win) {
      win.focus();
      win.print();
    }
  };

  const handleZoomIn = () => setScale((prev) => Math.min(prev + 0.15, 2.5));
  const handleZoomOut = () => setScale((prev) => Math.max(prev - 0.15, 0.5));
  const handleFitWidth = () => {
    if (!containerRef.current) return;
    const containerWidth = containerRef.current.clientWidth;
    const padding = containerWidth < 640 ? 24 : 48;
    setScale((containerWidth - padding) / 595.28);
  };

  return (
    <div className="h-screen w-screen flex flex-col bg-slate-100 overflow-hidden font-sans">
      {/* ─── Top Navbar ───────────────────────────────────────────────────── */}
      <header className="h-16 bg-white border-b border-gray-200 px-3 sm:px-6 flex items-center justify-between shadow-xs shrink-0 z-20">
        <div className="flex items-center gap-3 overflow-hidden min-w-0">
          <img src={LOGO_URL} alt="AVS Enterprises" className="h-9 w-auto object-contain shrink-0" />
          <div className="flex flex-col min-w-0">
            <div className="flex items-center gap-2">
              <span className="text-sm sm:text-base font-bold text-gray-900 truncate">
                {data?.invoiceNo ?? 'Invoice Document'}
              </span>
              {data?.customerName && (
                <span className="hidden sm:inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200 truncate">
                  {data.customerName}
                </span>
              )}
            </div>
            <div className="flex items-center gap-2 text-xs text-gray-500 truncate">
              <span className="font-medium text-gray-600">AVS Enterprises</span>
              {data?.invoiceDate && (
                <>
                  <span className="text-gray-300">•</span>
                  <span>{fmtDate(data.invoiceDate)}</span>
                </>
              )}
              {data?.grandTotal && (
                <>
                  <span className="text-gray-300">•</span>
                  <span className="font-semibold text-emerald-700">
                    {fmtCurrency(data.grandTotal)}
                  </span>
                </>
              )}
            </div>
          </div>
        </div>

        {/* Action Controls */}
        <div className="flex items-center gap-1.5 sm:gap-2 shrink-0">
          {pdfDoc && (
            <>
              {/* Zoom Controls (Desktop / Tablet) */}
              <div className="hidden md:flex items-center bg-gray-100 rounded-lg p-0.5 border border-gray-200 mr-1">
                <button
                  type="button"
                  onClick={handleZoomOut}
                  title="Zoom Out"
                  className="px-2 py-1 text-gray-600 hover:text-gray-900 font-bold hover:bg-white rounded transition-colors cursor-pointer"
                >
                  −
                </button>
                <span className="text-xs font-medium text-gray-600 px-2 select-none min-w-[45px] text-center">
                  {Math.round((scale / 1.25) * 100)}%
                </span>
                <button
                  type="button"
                  onClick={handleZoomIn}
                  title="Zoom In"
                  className="px-2 py-1 text-gray-600 hover:text-gray-900 font-bold hover:bg-white rounded transition-colors cursor-pointer"
                >
                  +
                </button>
                <button
                  type="button"
                  onClick={handleFitWidth}
                  title="Fit to Width"
                  className="px-2 py-1 text-xs text-gray-600 hover:text-gray-900 font-medium hover:bg-white rounded transition-colors cursor-pointer border-l border-gray-200"
                >
                  Fit
                </button>
              </div>

              {/* Print Button */}
              <button
                type="button"
                onClick={handlePrint}
                title="Print Invoice"
                className="hidden sm:inline-flex items-center gap-1.5 px-3 py-2 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 hover:text-gray-900 transition-colors shadow-2xs cursor-pointer"
              >
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <polyline points="6 9 6 2 18 2 18 9" />
                  <path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" />
                  <rect x="6" y="14" width="12" height="8" />
                </svg>
                <span>Print</span>
              </button>

              {/* Download Button */}
              <button
                id="btn-download-invoice-pdf"
                type="button"
                onClick={handleDownload}
                disabled={downloading}
                className="inline-flex items-center gap-1.5 sm:gap-2 px-3.5 sm:px-4 py-2 text-xs sm:text-sm font-semibold text-white bg-green-700 hover:bg-green-800 disabled:opacity-75 rounded-lg shadow-sm transition-colors cursor-pointer active:scale-98"
              >
                {downloading ? (
                  <>
                    <span className="w-3.5 h-3.5 rounded-full border-2 border-white/30 border-t-white animate-spin" />
                    <span>Downloading…</span>
                  </>
                ) : (
                  <>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.3" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                      <polyline points="7 10 12 15 17 10" />
                      <line x1="12" y1="15" x2="12" y2="3" />
                    </svg>
                    <span>Download</span>
                  </>
                )}
              </button>
            </>
          )}
        </div>
      </header>

      {/* ─── Main Viewport Area ────────────────────────────────────────────── */}
      <main
        ref={containerRef}
        className="flex-1 w-full h-[calc(100vh-64px)] overflow-y-auto overflow-x-auto bg-slate-200/80 flex flex-col items-center p-3 sm:p-6"
      >
        {loading && (
          <div className="flex flex-col items-center justify-center my-auto p-8 text-center">
            <div className="w-10 h-10 rounded-full border-3 border-gray-300 border-t-green-700 animate-spin mb-4" />
            <p className="text-base font-semibold text-gray-800">Rendering Invoice…</p>
            <p className="text-xs text-gray-500 mt-1">Preparing high-resolution view of your bill.</p>
          </div>
        )}

        {!loading && error && (
          <div className="flex flex-col items-center justify-center my-auto p-8 text-center max-w-md bg-white border border-gray-200 rounded-2xl shadow-md mx-4">
            <div className="w-12 h-12 rounded-full bg-red-50 text-red-600 flex items-center justify-center text-xl font-bold mb-3">
              !
            </div>
            <h2 className="text-lg font-bold text-gray-800">Invoice Not Available</h2>
            <p className="text-sm text-gray-500 mt-2">
              {error}
            </p>
          </div>
        )}

        {!loading && !error && pdfDoc && (
          <div className="flex flex-col items-center gap-4 w-full">
            {Array.from({ length: pdfDoc.numPages }, (_, idx) => (
              <div
                key={idx + 1}
                className="bg-white rounded-lg shadow-md border border-gray-300/80 overflow-hidden flex justify-center max-w-full"
              >
                <canvas
                  ref={(el) => {
                    canvasRefs.current[idx] = el;
                  }}
                  className="block"
                />
              </div>
            ))}
          </div>
        )}
      </main>
    </div>
  );
}