"use client";

import React, { useState, useRef, useEffect, useCallback } from "react";
import {
  ReceiptBoundingBoxes,
  BoundingBoxRect,
} from "@/lib/schema/receipt";
import {
  getFieldBoundingBox,
  hasExtractedBoundingBoxes,
} from "@/lib/utils/boundingBoxes";
import {
  ZoomIn,
  ZoomOut,
  RotateCw,
  Maximize2,
  Minimize2,
  Layers,
  FileSpreadsheet,
  Scan,
  Download,
} from "lucide-react";
import { useI18n } from "@/lib/i18n/context";
import { downloadReceiptImage } from "@/lib/utils/imageDownload";

export interface DocumentViewerProps {
  previewUrl?: string | null;
  fileName?: string;
  receiptId?: string;
  boundingBoxes?: ReceiptBoundingBoxes;
  activeHighlightField?: string | null;
  onSelectField?: (fieldKey: string) => void;
  className?: string;
}

interface TransformState {
  scale: number;
  translateX: number;
  translateY: number;
  rotation: number; // 0, 90, 180, 270
}

const MIN_SCALE = 0.25;
const MAX_SCALE = 5.0;
const SCALE_STEP = 0.25;

export function DocumentViewer({
  previewUrl,
  fileName,
  receiptId,
  boundingBoxes,
  activeHighlightField,
  onSelectField,
  className = "",
}: DocumentViewerProps) {
  const { language } = useI18n();
  const isDe = language === "de";

  const containerRef = useRef<HTMLDivElement>(null);
  const imageRef = useRef<HTMLImageElement>(null);

  const [transform, setTransform] = useState<TransformState>({
    scale: 1.0,
    translateX: 0,
    translateY: 0,
    rotation: 0,
  });

  const [showBoundingBoxes, setShowBoundingBoxes] = useState<boolean>(true);
  const [isDragging, setIsDragging] = useState<boolean>(false);
  const dragStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
  const transformAtDragStart = useRef<TransformState>({ ...transform });

  // Only overlay boxes that came from extraction — never the layout heuristic.
  const boxes = boundingBoxes;
  const canShowBoxes = hasExtractedBoundingBoxes(boxes);

  // Zoom Controls
  const handleZoomIn = useCallback(() => {
    setTransform((prev) => ({
      ...prev,
      scale: Math.min(MAX_SCALE, Math.round((prev.scale + SCALE_STEP) * 100) / 100),
    }));
  }, []);

  const handleZoomOut = useCallback(() => {
    setTransform((prev) => ({
      ...prev,
      scale: Math.max(MIN_SCALE, Math.round((prev.scale - SCALE_STEP) * 100) / 100),
    }));
  }, []);

  const handleResetZoom = useCallback(() => {
    setTransform((prev) => ({
      ...prev,
      scale: 1.0,
      translateX: 0,
      translateY: 0,
    }));
  }, []);

  const handleRotate = useCallback(() => {
    setTransform((prev) => ({
      ...prev,
      rotation: (prev.rotation + 90) % 360,
    }));
  }, []);

  const handleFitToPage = useCallback(() => {
    if (!containerRef.current || !imageRef.current) {
      setTransform({ scale: 1.0, translateX: 0, translateY: 0, rotation: 0 });
      return;
    }
    const container = containerRef.current.getBoundingClientRect();
    const naturalWidth = imageRef.current.naturalWidth || 600;
    const naturalHeight = imageRef.current.naturalHeight || 800;

    const scaleX = (container.width - 32) / naturalWidth;
    const scaleY = (container.height - 32) / naturalHeight;
    const fitScale = Math.min(Math.max(scaleX, scaleY, MIN_SCALE), 1.5);

    setTransform({
      scale: Math.round(fitScale * 100) / 100,
      translateX: 0,
      translateY: 0,
      rotation: 0,
    });
  }, []);

  // Pan (Mouse Drag)
  const handleMouseDown = (e: React.MouseEvent) => {
    // Only drag with primary mouse button
    if (e.button !== 0) return;
    setIsDragging(true);
    dragStartRef.current = { x: e.clientX, y: e.clientY };
    transformAtDragStart.current = { ...transform };
  };

  const handleMouseMove = (e: React.MouseEvent) => {
    if (!isDragging) return;
    const dx = e.clientX - dragStartRef.current.x;
    const dy = e.clientY - dragStartRef.current.y;

    setTransform((prev) => ({
      ...prev,
      translateX: transformAtDragStart.current.translateX + dx,
      translateY: transformAtDragStart.current.translateY + dy,
    }));
  };

  const handleMouseUp = () => {
    setIsDragging(false);
  };

  // Wheel Zoom (Ctrl+Wheel or Standard Wheel)
  const handleWheel = (e: React.WheelEvent) => {
    e.preventDefault();
    const delta = e.deltaY < 0 ? 0.15 : -0.15;
    setTransform((prev) => ({
      ...prev,
      scale: Math.max(MIN_SCALE, Math.min(MAX_SCALE, Math.round((prev.scale + delta) * 100) / 100)),
    }));
  };

  // Auto-center active bounding box if selected
  useEffect(() => {
    if (!activeHighlightField || !containerRef.current) return;
    const activeBox = getFieldBoundingBox(boxes, activeHighlightField);
    if (!activeBox) return;

    // If zoomed in, pan gently so active box is in focus
    if (transform.scale > 1.2) {
      const boxCenterYPercent = activeBox.y + activeBox.height / 2;
      const targetTranslateY = (50 - boxCenterYPercent) * (transform.scale * 3);
      setTransform((prev) => ({
        ...prev,
        translateY: Math.max(-500, Math.min(500, Math.round(targetTranslateY))),
      }));
    }
  }, [activeHighlightField, boxes, transform.scale]);

  // Collect all overlay items
  const renderBox = (
    box: BoundingBoxRect | undefined,
    fieldKey: string,
    label: string,
    extraTestId?: string
  ) => {
    if (!box) return null;
    const isActive = activeHighlightField && (
      activeHighlightField === fieldKey ||
      activeHighlightField.startsWith(fieldKey) ||
      (fieldKey === "totalAmount" && activeHighlightField === "gross") ||
      (fieldKey === "netAmount" && activeHighlightField === "net")
    );

    return (
      <div
        key={fieldKey}
        data-testid={extraTestId || `bbox-${fieldKey}`}
        data-field={fieldKey}
        onClick={(e) => {
          e.stopPropagation();
          onSelectField?.(fieldKey);
        }}
        title={`${label} (${isDe ? "Klicken zum Bearbeiten" : "Click to edit"})`}
        style={{
          left: `${box.x}%`,
          top: `${box.y}%`,
          width: `${box.width}%`,
          height: `${box.height}%`,
        }}
        className={`absolute cursor-pointer transition-all duration-150 rounded-none group select-none ${
          isActive
            ? "border-2 border-[#0066FF] bg-[#0066FF]/20 shadow-[0_0_0_2px_rgba(0,102,255,0.4)] z-20 animate-pulse"
            : "border border-black/30 hover:border-black hover:bg-black/10 z-10"
        }`}
      >
        <span
          className={`absolute -top-5 left-0 px-1.5 py-0.5 text-[9px] font-mono uppercase tracking-caps whitespace-nowrap transition-opacity pointer-events-none ${
            isActive
              ? "bg-[#0066FF] text-white opacity-100 font-bold z-30"
              : "bg-black text-white opacity-0 group-hover:opacity-100 z-20"
          }`}
        >
          {label}
        </span>
      </div>
    );
  };

  return (
    <div
      className={`flex flex-col h-full bg-[#0F172A] border border-[#E2E8F0] overflow-hidden select-none ${className}`}
      data-testid="document-viewer"
    >
      {/* Top Controls Toolbar */}
      <div className="flex flex-wrap items-center justify-between gap-2 px-3 py-2 bg-[#1E293B] border-b border-slate-700 text-white font-mono text-xs">
        {/* Zoom & Fit Group */}
        <div className="flex items-center gap-1">
          <button
            type="button"
            data-testid="viewer-zoom-out"
            onClick={handleZoomOut}
            disabled={transform.scale <= MIN_SCALE}
            className="p-1.5 rounded-none bg-slate-800 hover:bg-slate-700 disabled:opacity-40 text-slate-200 transition-colors"
            title={isDe ? "Verkleinern (-)" : "Zoom Out (-)"}
          >
            <ZoomOut className="w-3.5 h-3.5" />
          </button>
          <button
            type="button"
            data-testid="viewer-reset-zoom"
            onClick={handleResetZoom}
            className="px-2 py-1 bg-slate-800 hover:bg-slate-700 text-slate-200 text-[11px] font-mono tracking-caps transition-colors"
            title={isDe ? "100% Originalgröße" : "100% Original Size"}
          >
            {Math.round(transform.scale * 100)}%
          </button>
          <button
            type="button"
            data-testid="viewer-zoom-in"
            onClick={handleZoomIn}
            disabled={transform.scale >= MAX_SCALE}
            className="p-1.5 rounded-none bg-slate-800 hover:bg-slate-700 disabled:opacity-40 text-slate-200 transition-colors"
            title={isDe ? "Vergrößern (+)" : "Zoom In (+)"}
          >
            <ZoomIn className="w-3.5 h-3.5" />
          </button>
          <button
            type="button"
            data-testid="viewer-fit-page"
            onClick={handleFitToPage}
            className="p-1.5 rounded-none bg-slate-800 hover:bg-slate-700 text-slate-200 transition-colors ml-1"
            title={isDe ? "An Seite anpassen" : "Fit to Page"}
          >
            <Maximize2 className="w-3.5 h-3.5" />
          </button>
        </div>

        {/* Rotate, Download & Bounding Box Toggle */}
        <div className="flex items-center gap-1.5">
          <button
            type="button"
            data-testid="viewer-download"
            onClick={() =>
              downloadReceiptImage({
                previewUrl,
                originalFileName: fileName,
                id: receiptId || fileName || "receipt",
              })
            }
            disabled={!previewUrl}
            className="p-1.5 rounded-none bg-slate-800 hover:bg-slate-700 disabled:opacity-40 text-slate-200 transition-colors"
            title={
              previewUrl
                ? isDe
                  ? "Beleg-Bild herunterladen"
                  : "Download receipt image"
                : isDe
                ? "Keine Bildvorschau verfügbar"
                : "No image preview available"
            }
          >
            <Download className="w-3.5 h-3.5" />
          </button>

          <button
            type="button"
            data-testid="viewer-rotate"
            onClick={handleRotate}
            className="p-1.5 rounded-none bg-slate-800 hover:bg-slate-700 text-slate-200 transition-colors"
            title={isDe ? "90° im Uhrzeigersinn drehen" : "Rotate 90° Clockwise"}
          >
            <RotateCw className="w-3.5 h-3.5" />
          </button>

          <button
            type="button"
            data-testid="viewer-toggle-bbox"
            onClick={() => setShowBoundingBoxes((prev) => !prev)}
            disabled={!canShowBoxes}
            className={`flex items-center gap-1 px-2 py-1 text-[11px] font-mono uppercase tracking-caps transition-colors ${
              canShowBoxes && showBoundingBoxes
                ? "bg-[#0066FF] text-white"
                : "bg-slate-800 text-slate-400 hover:text-white disabled:opacity-40"
            }`}
            title={
              canShowBoxes
                ? isDe
                  ? "Bounding-Boxes ein-/ausblenden"
                  : "Toggle Bounding Boxes"
                : isDe
                  ? "Keine OCR-Koordinaten für diesen Beleg"
                  : "No OCR coordinates for this receipt"
            }
          >
            <Scan className="w-3 h-3" />
            <span className="hidden sm:inline">BBoxes</span>
          </button>
        </div>
      </div>

      {/* Main Interactive Canvas Area */}
      <div
        ref={containerRef}
        data-testid="viewer-canvas-container"
        onMouseDown={handleMouseDown}
        onMouseMove={handleMouseMove}
        onMouseUp={handleMouseUp}
        onMouseLeave={handleMouseUp}
        onWheel={handleWheel}
        className={`relative flex-1 flex items-center justify-center p-4 overflow-hidden bg-[#0A0F1D] ${
          isDragging ? "cursor-grabbing" : "cursor-grab"
        }`}
      >
        {previewUrl ? (
          <div
            data-testid="viewer-transform-layer"
            style={{
              transform: `translate(${transform.translateX}px, ${transform.translateY}px) scale(${transform.scale}) rotate(${transform.rotation}deg)`,
              transformOrigin: "center center",
              transition: isDragging ? "none" : "transform 0.1s ease-out",
            }}
            className="relative inline-block max-w-full max-h-full shadow-2xl bg-white"
          >
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img
              ref={imageRef}
              src={previewUrl}
              alt={fileName || (isDe ? "Belegdokument" : "Receipt Document")}
              data-testid="viewer-receipt-image"
              draggable={false}
              className="max-w-none max-h-[72vh] w-auto h-auto object-contain block border border-slate-700 select-none"
            />

            {/* Bounding Box Visual Overlay — only real OCR boxes, never heuristics */}
            {canShowBoxes && showBoundingBoxes && boxes && (
              <div
                data-testid="viewer-bbox-overlay"
                className="absolute inset-0 pointer-events-auto"
              >
                {renderBox(boxes.merchant, "merchant", isDe ? "Händler" : "Merchant")}
                {renderBox(boxes.date, "date", isDe ? "Datum" : "Date")}
                {renderBox(boxes.receiptNumber, "receiptNumber", isDe ? "Beleg-Nr." : "Receipt No.")}

                {boxes.lineItems?.map((box, idx) =>
                  renderBox(box, `lineItem:${idx}`, isDe ? `Pos. ${idx + 1}` : `Item ${idx + 1}`, `bbox-lineItem-${idx}`)
                )}

                {boxes.taxBreakdown?.map((box, idx) =>
                  renderBox(box, `taxBreakdown:${idx}`, isDe ? `MwSt. ${idx + 1}` : `Tax ${idx + 1}`, `bbox-tax-${idx}`)
                )}
                {renderBox(boxes.netAmount, "netAmount", isDe ? "Netto" : "Net")}
                {renderBox(boxes.totalAmount, "totalAmount", isDe ? "Brutto Gesamt" : "Gross Total")}
                {renderBox(boxes.paymentMethod, "paymentMethod", isDe ? "Zahlart" : "Payment")}
              </div>
            )}
          </div>
        ) : (
          <div className="flex flex-col items-center justify-center p-8 text-center text-slate-500 font-mono">
            <FileSpreadsheet className="w-12 h-12 mb-3 text-slate-600" />
            <p className="text-xs uppercase tracking-caps text-slate-400 font-bold mb-1">
              {isDe ? "Keine Bildvorschau verfügbar" : "No image preview available"}
            </p>
            <p className="text-[11px] text-slate-500 max-w-xs">
              {fileName || receiptId || (isDe ? "Belegdaten können in der rechten Spalte bearbeitet werden." : "Receipt data can be edited in the right column.")}
            </p>
          </div>
        )}
      </div>

      {/* Footer Navigation & Hint */}
      <div className="flex items-center justify-between px-3 py-1.5 bg-[#1E293B] border-t border-slate-700 text-slate-400 font-mono text-[10px] uppercase tracking-caps">
        <span className="truncate max-w-[200px]">{fileName || receiptId || (isDe ? "Beleg" : "Receipt")}</span>
        <span className="hidden sm:inline text-slate-500">
          {isDe ? "Ziehen zum Bewegen · Mausrad zum Zoomen" : "Drag to pan · Scroll wheel to zoom"}
        </span>
        <span>{transform.rotation}° CW</span>
      </div>
    </div>
  );
}
