"use client";

import { useState, useRef, useEffect, useCallback } from "react";
import { useRouter } from "next/navigation";
import {
  Camera,
  Keyboard,
  ArrowLeft,
  ScanLine,
  Loader2,
  AlertCircle,
  CheckCircle2,
} from "lucide-react";
import Link from "next/link";
import { validatePatientId } from "@/app/actions/patient";

type ScanState = "idle" | "starting" | "scanning" | "processing" | "error";

type CameraDevice = {
  id: string;
  label: string;
};

export default function PatientLoginPage() {
  const router = useRouter();
  const [scanState, setScanState] = useState<ScanState>("idle");
  const [error, setError] = useState("");
  const [manualId, setManualId] = useState("");
  const [showManualInput, setShowManualInput] = useState(false);
  const scannerRef = useRef<HTMLDivElement>(null);
  const html5QrCodeRef = useRef<any>(null);
  const [cameras, setCameras] = useState<CameraDevice[]>([]);
  const [selectedCameraId, setSelectedCameraId] = useState<string>("");

  const stopScanner = useCallback(async () => {
    console.log("[QR Scanner] stopScanner called");
    try {
      if (html5QrCodeRef.current) {
        console.log("[QR Scanner] Stopping scanner...");
        await html5QrCodeRef.current.stop();
        console.log("[QR Scanner] Scanner stopped successfully");
        console.log("[QR Scanner] Clearing scanner...");
        await html5QrCodeRef.current.clear();
        console.log("[QR Scanner] Scanner cleared successfully");
        html5QrCodeRef.current = null;
        console.log("[QR Scanner] Scanner reference reset to null");
      } else {
        console.log("[QR Scanner] No active scanner to stop");
      }
    } catch (err) {
      console.error("[QR Scanner] Error during stop/cleanup:", err);
    }
  }, []);

  useEffect(() => {
    return () => {
      console.log("[QR Scanner] Component unmounting — cleaning up scanner");
      stopScanner();
    };
  }, [stopScanner]);

  const extractPatientId = (text: string): string | null => {
    // Try parsing as URL
    try {
      const url = new URL(text);
      const match = url.pathname.match(/\/patient\/([^/]+)\/?$/);
      if (match) return match[1];
    } catch {
      // Not a valid URL
    }
    // Treat as raw ID if alphanumeric and reasonable length (CUIDs are ~25 chars)
    if (/^[a-zA-Z0-9_-]+$/.test(text) && text.length >= 10) {
      return text;
    }
    return null;
  };

  const handleScanSuccess = async (decodedText: string) => {
    console.log("[QR Scanner] Scan success, decoded text:", decodedText);
    await stopScanner();
    setScanState("processing");
    setError("");

    const patientId = extractPatientId(decodedText);

    if (!patientId) {
      console.warn("[QR Scanner] Could not extract valid patient ID from:", decodedText);
      setScanState("error");
      setError(
        "Could not read a valid Patient ID from the QR code. Please try again."
      );
      return;
    }

    console.log("[QR Scanner] Validated patientId:", patientId);
    const result = await validatePatientId(patientId);

    if (result.success) {
      console.log("[QR Scanner] Patient validated, redirecting to:", `/patient/${patientId}`);
      router.push(`/patient/${patientId}`);
    } else {
      console.error("[QR Scanner] Patient validation failed:", result.error);
      setScanState("error");
      setError(
        result.error || "Patient not found. Please check your QR code and try again."
      );
    }
  };

  const getCameras = async (): Promise<CameraDevice[]> => {
    console.log("[QR Scanner] Getting available cameras...");
    try {
      const { Html5Qrcode } = await import("html5-qrcode");
      const devices = await Html5Qrcode.getCameras();
      console.log("[QR Scanner] Found cameras:", devices);
      if (devices && devices.length) {
        return devices.map((d: any) => ({ id: d.id, label: d.label || `Camera ${d.id}` }));
      }
    } catch (err) {
      console.error("[QR Scanner] Error getting cameras:", err);
    }
    return [];
  };

  const requestCameraPermission = async (): Promise<boolean> => {
    console.log("[QR Scanner] Requesting camera permission...");
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: true });
      console.log("[QR Scanner] Camera permission granted");
      stream.getTracks().forEach((track) => track.stop());
      return true;
    } catch (err: any) {
      console.error("[QR Scanner] Camera permission denied or error:", err);
      if (err.name === "NotAllowedError" || err.name === "PermissionDeniedError") {
        setError("Camera access was denied. Please enable camera permissions in your browser settings and try again.");
      } else if (err.name === "NotFoundError") {
        setError("No camera found on this device.");
      } else {
        setError(`Camera error: ${err.message || err.name}. Please try again.`);
      }
      return false;
    }
  };

  const initializeScanner = async () => {
    console.log("[QR Scanner] initializeScanner called");

    // Prevent duplicate scanner starts
    if (html5QrCodeRef.current) {
      console.warn("[QR Scanner] Scanner already running. Stopping previous instance first...");
      await stopScanner();
    }

    try {
      const { Html5Qrcode } = await import("html5-qrcode");

      if (!scannerRef.current) {
        console.error("[QR Scanner] DOM element not found, retrying...");
        setScanState("error");
        setError("Scanner initialization failed. Please refresh and try again.");
        return;
      }

      // Request permission explicitly
      const permissionGranted = await requestCameraPermission();
      if (!permissionGranted) {
        console.warn("[QR Scanner] Permission not granted — aborting start");
        setScanState("error");
        return;
      }

      // Enumerate cameras and update state
      const cameraDevices = await getCameras();
      setCameras(cameraDevices);

      let cameraConfig: any = { facingMode: "environment" };
      if (cameraDevices.length > 0) {
        // Prefer environment-facing if label suggests it; otherwise use first
        const envCam = cameraDevices.find((c) =>
          c.label.toLowerCase().includes("back") || c.label.toLowerCase().includes("environment")
        );
        const camId = selectedCameraId || envCam?.id || cameraDevices[0].id;
        if (!selectedCameraId) {
          setSelectedCameraId(camId);
        }
        cameraConfig = { deviceId: { exact: camId } };
        console.log("[QR Scanner] Using camera ID:", camId);
      } else {
        console.warn("[QR Scanner] No cameras enumerated; falling back to facingMode: environment");
      }

      const html5QrCode = new Html5Qrcode("qr-reader");
      html5QrCodeRef.current = html5QrCode;
      console.log("[QR Scanner] Html5Qrcode instance created");

      await html5QrCode.start(
        cameraConfig,
        {
          fps: 10,
          qrbox: { width: 280, height: 280 },
          aspectRatio: 1.0,
        },
        (decodedText) => {
          console.log("[QR Scanner] onScanSuccess called with:", decodedText);
          handleScanSuccess(decodedText);
        },
        (scanFailure: any) => {
          // Scan failure fires continuously when no QR is present
          // Intentionally quiet to avoid console noise
        }
      );

      console.log("[QR Scanner] Scanner started successfully");
      setScanState("scanning");
    } catch (err: any) {
      console.error("[QR Scanner] Unexpected error during initializeScanner:", err);
      setScanState("error");
      if (!error) {
        setError(
          "Could not start the scanner. Please ensure camera permissions are granted and try again."
        );
      }
    }
  };

  const startScanning = async () => {
    setError("");
    setScanState("scanning");
    console.log("[QR Scanner] startScanning invoked — scheduling initialization");

    // Delay to allow React to render the scanner container in the DOM
    setTimeout(() => {
      initializeScanner();
    }, 150);
  };

  const handleManualSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!manualId.trim()) return;

    setScanState("processing");
    setError("");

    const result = await validatePatientId(manualId.trim());

    if (result.success) {
      router.push(`/patient/${manualId.trim()}`);
    } else {
      setScanState("error");
      setError(
        result.error || "Patient not found. Please check the ID and try again."
      );
    }
  };

  const handleCameraChange = async (e: React.ChangeEvent<HTMLSelectElement>) => {
    const newCameraId = e.target.value;
    console.log("[QR Scanner] Camera selection changed to:", newCameraId);
    setSelectedCameraId(newCameraId);
    if (scanState === "scanning" && html5QrCodeRef.current) {
      console.log("[QR Scanner] Restarting scanner with new camera...");
      await stopScanner();
      // Small delay to ensure cleanup before restart
      setTimeout(() => {
        startScanning();
      }, 300);
    }
  };

  return (
    <div className="min-h-screen bg-zinc-950 text-zinc-100 flex flex-col items-center justify-center px-4 py-8">
      <div className="w-full max-w-lg">
        {/* Back Link */}
        <Link
          href="/"
          className="inline-flex items-center gap-2 text-lg text-zinc-400 hover:text-zinc-200 transition-colors mb-10"
        >
          <ArrowLeft className="h-5 w-5" />
          Back to home
        </Link>

        {/* Header */}
        <div className="text-center mb-10">
          <div className="mx-auto mb-5 flex h-20 w-20 items-center justify-center rounded-full bg-rose-500/10">
            <ScanLine className="h-10 w-10 text-rose-400" />
          </div>
          <h1 className="text-4xl font-bold text-zinc-100 sm:text-5xl">
            Patient Login
          </h1>
          <p className="mt-4 text-2xl font-medium text-zinc-300 leading-relaxed">
            وجه كاميرا الهاتف نحو رمز QR الخاص بك للدخول
          </p>
          <p className="mt-2 text-lg text-zinc-500">
            Point your camera at your QR code to login
          </p>
        </div>

        {/* Error Message */}
        {error && (
          <div className="mb-8 rounded-2xl border border-red-500/20 bg-red-500/10 px-6 py-5 text-center">
            <AlertCircle className="mx-auto mb-2 h-8 w-8 text-red-400" />
            <p className="text-lg font-medium text-red-400">{error}</p>
            <button
              onClick={() => {
                setError("");
                setScanState("idle");
              }}
              className="mt-3 text-base text-red-300 underline underline-offset-4 hover:text-red-200"
            >
              Try again
            </button>
          </div>
        )}

        {/* Scanner Window */}
        {scanState === "scanning" && (
          <div className="mb-8 flex flex-col items-center">
            {cameras.length > 0 && (
              <div className="w-full max-w-sm mb-4">
                <label htmlFor="camera-select" className="block text-sm font-medium text-zinc-400 mb-2">
                  Select Camera
                </label>
                <select
                  id="camera-select"
                  value={selectedCameraId}
                  onChange={handleCameraChange}
                  className="w-full rounded-xl border border-zinc-700 bg-zinc-900 px-4 py-3 text-base text-zinc-100 outline-none focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 transition-colors"
                >
                  {cameras.map((camera) => (
                    <option key={camera.id} value={camera.id}>
                      {camera.label}
                    </option>
                  ))}
                </select>
              </div>
            )}
            <div className="relative w-full max-w-sm aspect-square rounded-3xl border-4 border-rose-500/30 bg-black overflow-hidden shadow-2xl shadow-rose-500/10">
              <div
                id="qr-reader"
                ref={scannerRef}
                className="w-full h-full"
              />
              {/* Scanning overlay */}
              <div className="absolute inset-0 pointer-events-none">
                <div className="absolute top-4 left-4 w-10 h-10 border-t-4 border-l-4 border-rose-400 rounded-tl-xl" />
                <div className="absolute top-4 right-4 w-10 h-10 border-t-4 border-r-4 border-rose-400 rounded-tr-xl" />
                <div className="absolute bottom-4 left-4 w-10 h-10 border-b-4 border-l-4 border-rose-400 rounded-bl-xl" />
                <div className="absolute bottom-4 right-4 w-10 h-10 border-b-4 border-r-4 border-rose-400 rounded-br-xl" />
                <div className="absolute top-1/2 left-0 right-0 h-0.5 bg-rose-400/50 animate-pulse" />
              </div>
            </div>
            <button
              onClick={async () => {
                await stopScanner();
                setScanState("idle");
                setError("");
              }}
              className="mt-6 inline-flex items-center gap-2 rounded-xl bg-zinc-800 px-8 py-4 text-lg font-semibold text-zinc-300 transition-colors hover:bg-zinc-700"
            >
              Cancel Scanning
            </button>
          </div>
        )}

        {/* Start Scanning Button */}
        {scanState === "idle" && (
          <div className="flex flex-col items-center gap-6">
            <button
              onClick={startScanning}
              className="flex w-full max-w-sm items-center justify-center gap-4 rounded-2xl bg-rose-600 px-8 py-6 text-2xl font-bold text-white transition-all hover:bg-rose-500 hover:scale-[1.02] active:scale-[0.98] shadow-xl shadow-rose-600/20"
            >
              <Camera className="h-8 w-8" />
              Start Scanning
            </button>

            <button
              onClick={() => setShowManualInput((v) => !v)}
              className="inline-flex items-center gap-2 text-lg text-zinc-400 hover:text-zinc-200 transition-colors"
            >
              <Keyboard className="h-5 w-5" />
              {showManualInput ? "Hide manual input" : "Enter ID manually"}
            </button>
          </div>
        )}

        {/* Starting / Processing State */}
        {(scanState === "starting" || scanState === "processing") && (
          <div className="flex flex-col items-center justify-center py-16">
            <Loader2 className="h-16 w-16 animate-spin text-rose-400" />
            <p className="mt-6 text-2xl font-semibold text-zinc-300">
              {scanState === "starting"
                ? "Starting camera..."
                : "Verifying..."}
            </p>
          </div>
        )}

        {/* Manual Input */}
        {showManualInput && scanState === "idle" && (
          <form
            onSubmit={handleManualSubmit}
            className="mt-8 rounded-2xl border border-zinc-800 bg-zinc-900/50 p-8"
          >
            <label
              htmlFor="patient-id"
              className="block text-xl font-semibold text-zinc-200 mb-4 text-center"
            >
              Enter your Patient ID
            </label>
            <input
              id="patient-id"
              type="text"
              value={manualId}
              onChange={(e) => setManualId(e.target.value)}
              placeholder="Paste or type your ID here"
              className="w-full rounded-xl border border-zinc-700 bg-zinc-950 px-6 py-4 text-xl text-zinc-100 placeholder-zinc-600 outline-none focus:border-rose-500 focus:ring-2 focus:ring-rose-500/20 transition-colors text-center"
            />
            <button
              type="submit"
              disabled={!manualId.trim()}
              className="mt-6 flex w-full items-center justify-center gap-3 rounded-xl bg-indigo-600 px-6 py-4 text-xl font-bold text-white transition-colors hover:bg-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <CheckCircle2 className="h-6 w-6" />
              Go to Dashboard
            </button>
          </form>
        )}
      </div>
    </div>
  );
}
