import { useState, useEffect, useRef } from "react";
import * as pdfjsLib from 'pdfjs-dist';
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorkerSrc;
import "./App.css";

function App() {
  // Worker reference
  const workerRef = useRef(null);

  // Application State
  const [modelStatus, setModelStatus] = useState("idle");
  const [progressItems, setProgressItems] = useState({});
  const [totalProgress, setTotalProgress] = useState(0);
  const [errorMsg, setErrorMsg] = useState("");
  const [loadTime, setLoadTime] = useState(null);

  // Performance metrics
  const [loadedDevice, setLoadedDevice] = useState("Detecting...");
  const [deviceConfig, setDeviceConfig] = useState("wasm");
  const [generationTime, setGenerationTime] = useState(null);

  // VLM State
  const [imageFile, setImageFile] = useState(null);
  const [imagePreviewUrl, setImagePreviewUrl] = useState("");
  const [extractedMetadata, setExtractedMetadata] = useState(null);
  const [isGenerating, setIsGenerating] = useState(false);

  // Initialize Web Worker
  useEffect(() => {
    workerRef.current = new Worker(new URL("./ai/worker.js", import.meta.url), {
      type: "module",
    });

    const onMessageReceived = (e) => {
      const { type, data, error } = e.data;

      switch (type) {
        case "progress":
          setProgressItems((prev) => {
            const newItems = { ...prev, [data.file]: data };
            const itemsArray = Object.values(newItems);
            const loaded = itemsArray.reduce((acc, item) => acc + (item.loaded || 0), 0);
            const total = itemsArray.reduce((acc, item) => acc + (item.total || 0), 0);
            if (total > 0) {
              setTotalProgress((loaded / total) * 100);
            }
            return newItems;
          });
          break;

        case "ready":
          setModelStatus("ready");
          setLoadedDevice(data.device === "webgpu" ? "WebGPU" : "WASM CPU");
          setLoadTime((performance.now() - loadTime) / 1000);
          break;

        case "completed":
          setExtractedMetadata(data.metadata);
          setGenerationTime(data.durationSec);
          setIsGenerating(false);
          break;

        case "error":
          console.error("Worker Error:", error);
          setErrorMsg(error);
          setModelStatus("error");
          setIsGenerating(false);
          break;

        default:
          break;
      }
    };

    workerRef.current.onmessage = onMessageReceived;

    // Auto-load model on mount (try WebGPU first)
    setModelStatus("loading");
    setProgressItems({});
    setTotalProgress(0);
    setErrorMsg("");
    setLoadTime(performance.now());
    workerRef.current.postMessage({ type: "load", data: { device: "wasm" } });

    // Clean up worker on unmount
    return () => {
      if (workerRef.current) {
        workerRef.current.terminate();
      }
    };
  }, []);

  function handleDeviceChange(newDevice) {
    if (isGenerating || modelStatus === "loading") return;
    setDeviceConfig(newDevice);
    setModelStatus("loading");
    setProgressItems({});
    setTotalProgress(0);
    setErrorMsg("");
    setLoadTime(performance.now());
    if (workerRef.current) {
      workerRef.current.postMessage({ type: "load", data: { device: newDevice } });
    }
  }

  async function handleClearCache() {
    if (window.confirm("Are you sure you want to delete the cached model files? This will require downloading the VLM weights again.")) {
      try {
        // Clear the custom IndexedDB cache
        await new Promise((resolve, reject) => {
          const req = indexedDB.deleteDatabase('transformers-cache');
          req.onsuccess = resolve;
          req.onerror = reject;
          req.onblocked = resolve;
        });

        // Clear fallback Cache API just in case
        const cacheKeys = await caches.keys();
        for (const key of cacheKeys) {
          if (key.includes("onnx") || key.includes("transformers") || key.includes("SmolVLM")) {
            await caches.delete(key);
          }
        }
        
        alert("Successfully cleared cached files from IndexedDB and Cache Storage!");
        window.location.reload();
      } catch (err) {
        alert("Failed to clear cache: " + err.message);
      }
    }
  }

  async function handleImageUpload(e) {
    const file = e.target.files[0];
    if (!file) return;

    setImageFile(file);
    setExtractedMetadata(null);
    setGenerationTime(null);

    if (file.type === "application/pdf") {
      try {
        const arrayBuffer = await file.arrayBuffer();
        const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
        const page = await pdf.getPage(1);
        const viewport = page.getViewport({ scale: 2.0 });
        
        const canvas = document.createElement("canvas");
        const context = canvas.getContext("2d");
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        
        await page.render({ canvasContext: context, viewport }).promise;
        const dataUrl = canvas.toDataURL("image/png");
        setImagePreviewUrl(dataUrl);
      } catch (err) {
        console.error("PDF Parsing error:", err);
        alert("Failed to read PDF.");
      }
    } else {
      const reader = new FileReader();
      reader.onload = (ev) => {
        setImagePreviewUrl(ev.target.result);
      };
      reader.readAsDataURL(file);
    }
  }

  function handleExtractName() {
    if (!imagePreviewUrl || isGenerating || modelStatus !== "ready") return;

    setIsGenerating(true);
    setExtractedMetadata(null);
    setGenerationTime(null);

    const img = new Image();
    img.onload = () => {
      // Crop 1: Top Quarter (25%)
      const canvasQuarter = document.createElement("canvas");
      const ctxQuarter = canvasQuarter.getContext("2d");
      canvasQuarter.width = img.width;
      canvasQuarter.height = img.height * 0.25;
      ctxQuarter.drawImage(img, 0, 0, img.width, img.height * 0.25, 0, 0, canvasQuarter.width, canvasQuarter.height);
      // Crop: Top Half (50%) — enough context for both header info and subject deduction
      const canvasHalf = document.createElement("canvas");
      const ctxHalf = canvasHalf.getContext("2d");
      canvasHalf.width = img.width;
      canvasHalf.height = img.height * 0.50;
      ctxHalf.drawImage(img, 0, 0, img.width, img.height * 0.50, 0, 0, canvasHalf.width, canvasHalf.height);
      const croppedHalf = canvasHalf.toDataURL("image/png");

      if (workerRef.current) {
        workerRef.current.postMessage({
          type: "generate",
          data: {
            imageFileOrUrlTopHalf: croppedHalf,
            requestId: "vlm-extract"
          }
        });
      }
    };
    img.src = imagePreviewUrl;
  }

  function handleDownloadRenamed() {
    if (!imageFile || !extractedMetadata) return;

    // Clean name: remove all spaces, punctuation, leaving only alphanumeric
    const cleanName = (extractedMetadata.name || "Unknown")
      .replace(/[^a-zA-Z0-9]/g, "");
    
    // Clean roll number: remove any non-alphanumeric characters (like trailing periods)
    const cleanRoll = (extractedMetadata.rollNo || "")
      .replace(/[^a-zA-Z0-9]/g, "");

    // Map subjects to their clean abbreviations (Maths, Bio, Phy, Chem, Eco)
    const rawSubject = (extractedMetadata.subject || "").trim().toLowerCase();
    let subAbbr = "Sub";
    if (rawSubject.includes("math")) subAbbr = "Maths";
    else if (rawSubject.includes("bio")) subAbbr = "Bio";
    else if (rawSubject.includes("phys")) subAbbr = "Phy";
    else if (rawSubject.includes("chem")) subAbbr = "Chem";
    else if (rawSubject.includes("econ")) subAbbr = "Eco";
    else {
      // Fallback: clean the subject string and capitalize it
      const cleaned = rawSubject.replace(/[^a-z0-9]/gi, '');
      subAbbr = cleaned ? (cleaned.charAt(0).toUpperCase() + cleaned.slice(1)) : "Sub";
    }

    // Retain original extension (default to .pdf if missing)
    const extension = imageFile.name.includes('.') ? imageFile.name.split('.').pop() : 'pdf';
    
    // Format: StudentNameROLL_sub (e.g. AadarshPatel21_Maths.pdf)
    const newFilename = `${cleanName}${cleanRoll}_${subAbbr}.${extension}`;

    // Create download link
    const url = URL.createObjectURL(imageFile);
    const a = document.createElement('a');
    a.href = url;
    a.download = newFilename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }

  return (
    <div className="app-container">
      {/* Header Panel */}
      <div className="header-section">
        <div className="title-group">
          <h1>Student Name Extractor</h1>
          <p>Powered by SmolVLM-500M-Instruct running {modelStatus === "ready" && loadedDevice === "WebGPU" ? "on GPU via WebGPU" : "on CPU via WebAssembly"}</p>
          <div className="backend-control" style={{ marginTop: "10px", display: "flex", gap: "12px", alignItems: "center", flexWrap: "wrap" }}>
            <div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
              <span style={{ fontSize: "13px", color: "rgba(255, 255, 255, 0.6)" }}>Device: <strong>WebAssembly (CPU)</strong></span>
            </div>

            <button
              onClick={handleClearCache}
              disabled={modelStatus === "loading" || isGenerating}
              style={{
                background: "rgba(239, 68, 68, 0.15)",
                border: "1px solid rgba(239, 68, 68, 0.3)",
                borderRadius: "6px",
                color: "#f87171",
                padding: "4px 8px",
                fontSize: "12px",
                cursor: "pointer",
                display: "flex",
                alignItems: "center",
                gap: "4px",
              }}
            >
              🗑️ Clear Storage Cache
            </button>
          </div>
        </div>
        <div className="model-badge">
          <span className={`pulse-dot ${modelStatus}`}></span>
          {modelStatus === "idle" && "Model Not Loaded"}
          {modelStatus === "loading" && `Downloading Weights: ${totalProgress.toFixed(0)}%`}
          {modelStatus === "ready" && `Model Ready (${loadedDevice})`}
          {modelStatus === "error" && "Load Failed"}
        </div>
      </div>


      {/* Main Content Area */}
      {modelStatus === "error" && (
        <div className="error-banner">
          ⚠️ <strong>Error loading model:</strong> {errorMsg}
          <br />
          <button onClick={() => window.location.reload()} style={{ marginTop: "10px", padding: "5px 10px", borderRadius: "4px", background: "rgba(255,255,255,0.1)", color: "white", border: "none", cursor: "pointer" }}>Retry Loading</button>
        </div>
      )}

      {modelStatus !== "ready" && modelStatus !== "error" && (
        <div className="glass-panel" style={{ textAlign: "center", padding: "60px 20px" }}>
          <h2>Initializing VLM Scanner Engine</h2>
          <p style={{ color: "rgba(255,255,255,0.7)", marginTop: "10px", marginBottom: "30px" }}>
            Downloading and compiling the SmolVLM-500M-Instruct model. <br />
            This will take a few minutes on the first run as it caches the ~800MB weights.
          </p>
          <div className="progress-container" style={{ width: "80%", margin: "0 auto", height: "12px", background: "rgba(255,255,255,0.1)", borderRadius: "6px", overflow: "hidden" }}>
            <div className="progress-bar" style={{ width: `${totalProgress}%`, height: "100%", background: "var(--primary)", transition: "width 0.3s ease" }}></div>
          </div>
        </div>
      )}

      {modelStatus === "ready" && (
        <div className="vlm-scanner-container" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "20px" }}>
          
          {/* Upload Panel */}
          <div className="glass-panel" style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
            <h3>1. Upload Document</h3>
            <p style={{ fontSize: "14px", color: "rgba(255,255,255,0.6)" }}>
              Upload an image of a document (PNG, JPG, WebP) containing a student's name.
            </p>
            
            <div 
              style={{
                border: "2px dashed rgba(255,255,255,0.2)",
                borderRadius: "12px",
                padding: "40px",
                textAlign: "center",
                position: "relative",
                cursor: "pointer",
                transition: "all 0.2s ease",
                backgroundColor: "rgba(0,0,0,0.2)"
              }}
              onClick={() => document.getElementById("file-upload").click()}
            >
              <input 
                id="file-upload" 
                type="file" 
                accept="image/*,application/pdf" 
                onChange={handleImageUpload} 
                style={{ display: "none" }} 
              />
              <span style={{ fontSize: "32px", display: "block", marginBottom: "10px" }}>📄</span>
              <span style={{ fontWeight: "500" }}>Click to select a document</span>
            </div>

              {imagePreviewUrl && (
              <button 
                onClick={handleExtractName} 
                disabled={isGenerating}
                className="send-button"
                style={{ padding: "14px", width: "100%", fontSize: "16px", borderRadius: "8px", marginTop: "auto" }}
              >
                {isGenerating ? "Scanning Document..." : "Extract Metadata"}
              </button>
            )}
          </div>

          {/* Preview & Results Panel */}
          <div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
            
            <div className="glass-panel" style={{ flex: 1, display: "flex", flexDirection: "column" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "15px" }}>
                <h3 style={{ margin: 0 }}>Document Preview</h3>
              </div>
              
              <div style={{ 
                flex: 1, 
                backgroundColor: "rgba(0,0,0,0.3)", 
                borderRadius: "8px", 
                display: "flex", 
                alignItems: "center", 
                justifyContent: "center",
                overflow: "hidden",
                minHeight: "250px"
              }}>
                {imagePreviewUrl ? (
                  <img src={imagePreviewUrl} alt="Document Preview" style={{ maxWidth: "100%", maxHeight: "300px", objectFit: "contain" }} />
                ) : (
                  <span style={{ color: "rgba(255,255,255,0.3)", fontSize: "14px" }}>No document selected</span>
                )}
              </div>
            </div>

            {/* Document Metadata Panel */}
            <div className="glass-panel" style={{ flex: 1, display: "flex", flexDirection: "column" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "15px" }}>
                <h3 style={{ margin: 0, fontSize: "14px", letterSpacing: "1px", color: "rgba(255,255,255,0.6)" }}>EXTRACTED METADATA</h3>
                <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
                  {generationTime && (
                    <span style={{ fontSize: "12px", color: "rgba(255, 255, 255, 0.4)" }}>
                      Processed in {generationTime}s
                    </span>
                  )}
                  {isGenerating && <span className="pulse-dot"></span>}
                </div>
              </div>
              
              <div style={{ 
                padding: "20px", 
                backgroundColor: "rgba(0,0,0,0.2)", 
                borderRadius: "8px",
                border: "1px solid rgba(255,255,255,0.05)",
                textAlign: "left",
                flex: 1,
                display: "flex",
                flexDirection: "column",
                gap: "15px"
              }}>
                {isGenerating ? (
                   <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.4)" }}>
                     Analyzing document structure...
                   </div>
                ) : extractedMetadata ? (
                   <>
                     <div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
                        <span style={{ fontSize: "12px", color: "rgba(255,255,255,0.5)", textTransform: "uppercase" }}>Student Name</span>
                        <strong style={{ fontSize: "18px", color: "var(--primary)" }}>{extractedMetadata.name || "--"}</strong>
                     </div>
                     <div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
                        <span style={{ fontSize: "12px", color: "rgba(255,255,255,0.5)", textTransform: "uppercase" }}>Subject / Course</span>
                        <strong style={{ fontSize: "18px", color: "white" }}>{extractedMetadata.subject || "--"}</strong>
                     </div>
                     <div style={{ display: "flex", flexDirection: "column", gap: "5px" }}>
                        <span style={{ fontSize: "12px", color: "rgba(255,255,255,0.5)", textTransform: "uppercase" }}>Roll Number / ID</span>
                        <strong style={{ fontSize: "18px", color: "white" }}>{extractedMetadata.rollNo || "--"}</strong>
                     </div>
                     
                     <div style={{ marginTop: "auto", paddingTop: "20px" }}>
                       <button 
                         onClick={handleDownloadRenamed} 
                         style={{ 
                           width: "100%", 
                           padding: "12px", 
                           backgroundColor: "rgba(16, 185, 129, 0.2)", 
                           color: "#34d399", 
                           border: "1px solid rgba(16, 185, 129, 0.4)", 
                           borderRadius: "6px", 
                           cursor: "pointer",
                           fontWeight: "bold",
                           display: "flex",
                           justifyContent: "center",
                           alignItems: "center",
                           gap: "8px"
                         }}
                       >
                         ⬇️ Download Renamed File
                       </button>
                     </div>
                   </>
                ) : (
                   <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.4)" }}>
                     Metadata will appear here
                   </div>
                )}
              </div>
            </div>

          </div>
        </div>
      )}
    </div>
  );
}

export default App;