"use client";

import React, { useEffect, useMemo, useRef, useState } from "react";
import { QRScanner, QRScannerHandle } from "@/components/qr/QRScanner";
import { useAuth } from "@/hooks/useAuth";
import { apiFetch } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";
import { useRouter } from "next/navigation";

export default function TicketScanningPage() {
  const router = useRouter();
  const scannerRef = useRef<QRScannerHandle>(null);
  const [lastResult, setLastResult] = useState<string | null>(null);
  const [scanInfo, setScanInfo] = useDismissingState<string | null>(null);
  const [error, setError] = useDismissingState<string | null>(null);
  const [alreadyUsedModal, setAlreadyUsedModal] = useState<{ message: string; ticket?: any } | null>(null);
  const [errorModal, setErrorModal] = useState<string | null>(null);
  const { token, user } = useAuth();
  const [recentScans, setRecentScans] = useState<any[]>([]);
  const [stats, setStats] = useState<any | null>(null);
  const [loadingStats, setLoadingStats] = useState<boolean>(false);
  const [successModal, setSuccessModal] = useState<{
    optionName: string;
    ticketId: string;
    eventTitle: string;
    qtyRedeemed: number;
    remaining: number;
    total: number;
  } | null>(null);

  // Confirm step state
  const [confirmModal, setConfirmModal] = useState<{
    qrCode: string;
    ticket: any;
    remaining: number;
  } | null>(null);
  const [confirmQty, setConfirmQty] = useState(1);
  const [confirmQtyRaw, setConfirmQtyRaw] = useState("1");

  // Event selection state
  const [allEvents, setAllEvents] = useState<any[]>([]);
  const [includePastEvents, setIncludePastEvents] = useState(false);
  const [selectedEventId, setSelectedEventId] = useState<string>("all");
  const [loadingEvents, setLoadingEvents] = useState<boolean>(false);
  const [sections, setSections] = useState<any[]>([]);
  const [selectedSectionId, setSelectedSectionId] = useState<string>("all");
  const [loadingSections, setLoadingSections] = useState(false);

  // All events from API (including past); frontend filters to 12h window or all past
  useEffect(() => {
    (async () => {
      try {
        if (!token) return;
        setLoadingEvents(true);
        const evs = await apiFetch<any[]>("/api/events/all?includePast=true", { authToken: token });
        const sorted = (evs || []).sort((a, b) => new Date(a.endDate).getTime() - new Date(b.endDate).getTime());
        setAllEvents(sorted);
      } catch (e: any) {
        // non-fatal
      } finally {
        setLoadingEvents(false);
      }
    })();
  }, [token]);

  const events = useMemo(() => {
    if (includePastEvents) return allEvents;
    const cutoff = Date.now() - 12 * 60 * 60 * 1000;
    return allEvents.filter(ev => {
      const t = new Date(ev.endDate).getTime();
      return !isNaN(t) && t >= cutoff;
    });
  }, [allEvents, includePastEvents]);

  useEffect(() => {
    (async () => {
      if (!token || !selectedEventId || selectedEventId === "all") {
        setSections([]);
        setSelectedSectionId("all");
        return;
      }
      try {
        setLoadingSections(true);
        const list = await apiFetch<any[]>(`/api/sections?eventId=${selectedEventId}`, { authToken: token });
        setSections(Array.isArray(list) ? list : []);
        setSelectedSectionId("all");
      } catch {
        setSections([]);
      } finally {
        setLoadingSections(false);
      }
    })();
  }, [selectedEventId, token]);

  // Bug fix: stop the scanner when the event or section filter changes so stale scan
  // context is never used. The user must press "Scan Ticket" again to resume.
  const isFirstFilterRender = useRef(true);
  useEffect(() => {
    if (isFirstFilterRender.current) { isFirstFilterRender.current = false; return; }
    scannerRef.current?.stop();
  }, [selectedEventId, selectedSectionId]);

  async function handleResult(text: string) {
    setLastResult(text);
    setError(null);
    setScanInfo(null);
    try {
      if (!token) {
        setErrorModal("Please login as staff to scan tickets.");
        return;
      }

      // Always preview first to validate the ticket before showing confirm step
      // Uses the lightweight scan-preview endpoint (only fetches fields needed for the confirm modal)
      let preview: any;
      try {
        preview = await apiFetch<any>(`/api/tickets/scan-preview/${encodeURIComponent(text)}`, { authToken: token });
      } catch (pe: any) {
        setErrorModal(pe?.message || 'Failed to validate ticket');
        return;
      }

      // Validate event
      if (selectedEventId && selectedEventId !== "all") {
        const ticketEventId = preview?.event?.id || preview?.eventId;
        if (ticketEventId && ticketEventId !== selectedEventId) {
          const eventTitle = preview?.event?.title || 'Event';
          setErrorModal(`This ticket is for a different event: ${eventTitle}`);
          return;
        }

        // Validate section
        if (selectedSectionId !== "all") {
          const ticketOptionId = preview?.registrationOption?.eventOption?.id || preview?.eventOptionId;
          if (!ticketOptionId) {
            setErrorModal("Unable to determine ticket type");
            return;
          }
          const section = sections.find(s => s.id === selectedSectionId);
          const allowedOptionIds = (section?.allowedOptions || []).map((o: any) => o.eventOptionId);
          if (!allowedOptionIds.includes(ticketOptionId)) {
            setErrorModal("This ticket is not valid for this section");
            return;
          }
        }
      }

      // Compute remaining qty
      const ticketQty = preview?.quantity || 1;
      const totalRedeemed = (preview?.usages || []).reduce((s: number, u: any) => s + (u.quantityRedeemed || 1), 0);
      const remaining = ticketQty - totalRedeemed;

      if (remaining <= 0) {
        setAlreadyUsedModal({ message: 'Ticket has already been fully used', ticket: preview });
        return;
      }

      // Show confirm step
      setConfirmQty(remaining);
      setConfirmQtyRaw(String(remaining));
      setConfirmModal({ qrCode: text, ticket: preview, remaining });
    } catch (e: any) {
      setErrorModal(e?.message || "Failed to scan ticket");
    }
  }

  async function commitScan() {
    if (!confirmModal || !token) return;

    // Capture everything before clearing modal state
    const { qrCode, ticket, remaining } = confirmModal;
    const qty = confirmQty;
    const baseName = ticket?.registrationOption?.eventOption?.name || "Ticket";
    const variantName = ticket?.registrationOption?.variant?.name;
    const optionName = variantName ? `${baseName} — ${variantName}` : baseName;
    const eventTitle = ticket?.event?.title || 'Event';
    const idPart = ticket?.id ? String(ticket.id).slice(0, 6) : '';
    const newRemaining = remaining - qty;

    // Show success immediately — we already have all the data from the preview step.
    // The actual write happens in the background so the user sees an instant response.
    setConfirmModal(null);
    setScanInfo(`Ticket #${idPart} — ${optionName} — ${eventTitle}`);
    setSuccessModal({
      optionName,
      ticketId: idPart,
      eventTitle,
      qtyRedeemed: qty,
      remaining: newRemaining,
      total: ticket?.quantity || 1,
    });

    // Background write — reverse the optimistic update on failure
    try {
      const url = `/api/tickets/scan/${encodeURIComponent(qrCode)}${
        selectedEventId && selectedEventId !== "all" ? `?eventId=${encodeURIComponent(selectedEventId)}` : ''
      }`;
      await apiFetch<any>(url, {
        method: "POST",
        authToken: token,
        body: { qty },
      });
      refreshStatsAndRecent();
    } catch (e: any) {
      setSuccessModal(null);
      setScanInfo(null);
      const raw = e?.message || "Failed to scan ticket";
      try {
        const parsed = JSON.parse(raw);
        const msg: string | undefined = parsed?.message;
        if (msg && /already\s*(been)?\s*used/i.test(msg)) {
          setAlreadyUsedModal({ message: msg, ticket: parsed?.ticket });
          return;
        }
        setErrorModal(msg || raw);
      } catch {
        setErrorModal(raw);
      }
    }
  }

  const loadRecent = async () => {
    if (!token) return;
    try {
      const list = await apiFetch<any[]>(`/api/tickets/scans/recent?limit=10`, { authToken: token });
      setRecentScans(list);
    } catch {}
  };
  const loadStats = async () => {
    if (!token) return;
    try {
      setLoadingStats(true);
      const s = await apiFetch<any>(`/api/tickets/scans/stats`, { authToken: token });
      setStats(s);
    } catch {} finally {
      setLoadingStats(false);
    }
  };
  const refreshStatsAndRecent = () => { loadRecent(); loadStats(); };
  useEffect(() => {
    refreshStatsAndRecent();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [token]);

  return (
    <div className="max-w-6xl mx-auto w-full p-4">
      <div className="grid lg:grid-cols-3 gap-6">
        <div className="lg:col-span-2">
          <div className="flex items-center justify-between mb-4">
            <h1 className="text-2xl font-semibold">Ticket Scanning</h1>
            <button className="px-3 py-1.5 text-sm rounded bg-gray-100 hover:bg-gray-200 text-gray-800 shadow-sm" onClick={() => router.push('/dashboard')}>Back</button>
          </div>
          <p className="text-sm text-gray-600 mb-4">
            Use the button to start/stop scanning. The back camera will be used when available.
          </p>

          {/* Event filter */}
          <div className="flex flex-col sm:flex-row sm:flex-wrap sm:items-center gap-2 mb-3">
            <label className="text-sm text-gray-700 shrink-0">Event</label>
            <select
              className="border rounded px-3 py-2 w-full sm:w-56 max-w-full"
              value={selectedEventId}
              onChange={(e) => setSelectedEventId(e.target.value)}
            >
              <option value="all">All events</option>
              {events.map((ev) => (
                <option key={ev.id} value={ev.id}>{ev.title}</option>
              ))}
            </select>
            <label className="flex items-center gap-1.5 text-sm text-gray-600 cursor-pointer">
              <input type="checkbox" checked={includePastEvents} onChange={e => setIncludePastEvents(e.target.checked)} />
              Include past events
            </label>
            {loadingEvents && <span className="text-xs text-gray-500">Loading events…</span>}
          </div>
          {sections.length > 0 && (
            <div className="flex flex-col sm:flex-row sm:items-center gap-2 mb-3">
              <label className="text-sm text-gray-700 shrink-0">Section</label>
              <select
                className="border rounded px-3 py-2 w-full sm:w-56 max-w-full"
                value={selectedSectionId}
                onChange={(e) => setSelectedSectionId(e.target.value)}
              >
                <option value="all">All sections</option>
                {sections.map(section => (
                  <option key={section.id} value={section.id}>{section.name}</option>
                ))}
              </select>
              {loadingSections && <span className="text-xs text-gray-500">Loading sections…</span>}
            </div>
          )}

          <QRScanner
            ref={scannerRef}
            onResult={handleResult}
            paused={!!(confirmModal || alreadyUsedModal || errorModal || successModal)}
          />

          {scanInfo && (
            <div className="mt-2 p-3 border rounded bg-green-50 text-green-800 text-sm">{scanInfo}</div>
          )}
          {error && (
            <div className="mt-2 p-3 border rounded bg-red-50 text-red-800 text-sm">{error}</div>
          )}
        </div>

        <div>
          <h2 className="text-xl font-semibold mb-3">Scanner Stats</h2>
          {loadingStats && <div className="text-sm text-gray-500 mb-2">Loading stats…</div>}
          {stats && (
            <div className="grid grid-cols-3 gap-2 mb-3">
              <div className="border rounded p-3 bg-white">
                <div className="text-xs text-gray-500">Today</div>
                <div className="text-lg font-semibold">{stats.totalToday}</div>
              </div>
              <div className="border rounded p-3 bg-white">
                <div className="text-xs text-gray-500">My scans</div>
                <div className="text-lg font-semibold">{stats.myToday}</div>
              </div>
              <div className="border rounded p-3 bg-white">
                <div className="text-xs text-gray-500">Last hour</div>
                <div className="text-lg font-semibold">{stats.lastHour}</div>
              </div>
            </div>
          )}

          {stats?.byStaff?.length > 0 && (
            <div className="mb-4">
              <div className="text-sm font-medium mb-1">Today by staff</div>
              <ul className="text-sm text-gray-700 space-y-1">
                {stats.byStaff.map((s: any) => (
                  <li key={s.scannedById} className="flex justify-between">
                    <span>{s.name || 'Staff'}</span>
                    <span className="font-medium">{s.count}</span>
                  </li>
                ))}
              </ul>
            </div>
          )}

          <h3 className="text-lg font-semibold mb-2">Last 10 scans</h3>
          <ul className="text-sm space-y-2 max-h-80 overflow-auto pr-2">
            {recentScans.map((u: any) => (
              <li key={u.id} className="border rounded p-2 bg-white">
                <div className="flex justify-between">
                  <div className="font-medium">{u.ticket?.event?.title || 'Event'}</div>
                  <div className="text-xs text-gray-500">{new Date(u.scannedAt).toLocaleString()}</div>
                </div>
                <div className="text-xs text-gray-600">
                  {u.ticket?.registrationOption?.eventOption?.name || 'Ticket'}{u.ticket?.registrationOption?.variant?.name ? ` — ${u.ticket.registrationOption.variant.name}` : ''}
                  {u.quantityRedeemed && u.quantityRedeemed > 1 ? ` ×${u.quantityRedeemed}` : ''}
                  {' — '}#{String(u.ticket?.id || '').slice(0,8)}
                </div>
                <div className="text-xs text-gray-500">Scanned by: {u.scannedBy?.name || u.scannedById}</div>
              </li>
            ))}
            {recentScans.length === 0 && <li className="text-gray-500">No scans yet.</li>}
          </ul>
        </div>
      </div>

      {/* ── Confirm scan modal ───────────────────────────────────────────── */}
      {confirmModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white rounded-xl shadow-lg max-w-md w-full p-6">
            <h3 className="text-lg font-semibold mb-1 text-indigo-700">Confirm Scan</h3>
            <p className="text-sm text-gray-500 mb-4">Review the ticket details before confirming.</p>

            <div className="bg-gray-50 border rounded-lg p-4 mb-4 space-y-1 text-sm">
              <div><span className="font-medium">Ticket type:</span> {confirmModal.ticket?.registrationOption?.eventOption?.name || 'Ticket'}{confirmModal.ticket?.registrationOption?.variant?.name ? ` — ${confirmModal.ticket.registrationOption.variant.name}` : ''}</div>
              <div><span className="font-medium">Event:</span> {confirmModal.ticket?.event?.title || '—'}</div>
              <div><span className="font-medium">Holder:</span> {confirmModal.ticket?.user?.name || confirmModal.ticket?.registrationOption?.registration?.user?.name || '—'}</div>
              <div><span className="font-medium">Qty on ticket:</span> {confirmModal.ticket?.quantity || 1}</div>
              <div><span className="font-medium">Remaining:</span> <span className={confirmModal.remaining < (confirmModal.ticket?.quantity || 1) ? 'text-amber-600 font-semibold' : 'text-green-700 font-semibold'}>{confirmModal.remaining}</span></div>
            </div>

            {(confirmModal.ticket?.quantity || 1) > 1 && (
              <div className="mb-4">
                <label className="block text-sm font-medium text-gray-700 mb-1">Qty to redeem (max {confirmModal.remaining})</label>
                <input
                  type="text"
                  inputMode="numeric"
                  min={1}
                  max={confirmModal.remaining}
                  className="w-24 border rounded px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400"
                  value={confirmQtyRaw}
                  onChange={e => setConfirmQtyRaw(e.target.value)}
                  onBlur={() => {
                    const parsed = parseInt(confirmQtyRaw, 10);
                    const clamped = isNaN(parsed) ? 1 : Math.min(confirmModal.remaining, Math.max(1, parsed));
                    setConfirmQty(clamped);
                    setConfirmQtyRaw(String(clamped));
                  }}
                />
              </div>
            )}

            <div className="flex gap-3">
              <button
                onClick={() => setConfirmModal(null)}
                className="flex-1 px-4 py-2 rounded-lg border text-sm font-medium text-gray-700 hover:bg-gray-50"
              >
                Cancel
              </button>
              <button
                onClick={commitScan}
                className="flex-1 px-4 py-2 rounded-lg bg-indigo-600 text-white text-sm font-semibold hover:bg-indigo-700"
              >
                Confirm Scan
              </button>
            </div>
          </div>
        </div>
      )}

      {/* ── Already used modal ───────────────────────────────────────────── */}
      {alreadyUsedModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white rounded shadow-lg max-w-md w-full p-5">
            <h3 className="text-lg font-semibold mb-2 text-red-600">Ticket Already Scanned</h3>
            <p className="text-sm text-gray-700 mb-3">{alreadyUsedModal.message}</p>
            {alreadyUsedModal.ticket && (
              <div className="text-xs text-gray-600 bg-gray-50 p-3 rounded border">
                <div><span className="font-medium">Ticket ID:</span> {alreadyUsedModal.ticket.id}</div>
                {alreadyUsedModal.ticket.event?.title && (
                  <div><span className="font-medium">Event:</span> {alreadyUsedModal.ticket.event.title}</div>
                )}
                {Array.isArray(alreadyUsedModal.ticket.usages) && alreadyUsedModal.ticket.usages.length > 0 && (
                  <div className="mt-2">
                    <div className="font-medium">Usages:</div>
                    <ul className="list-disc ml-5 mt-1 max-h-32 overflow-auto">
                      {alreadyUsedModal.ticket.usages.map((u: any) => (
                        <li key={u.id}>{new Date(u.scannedAt).toLocaleString()}{u.quantityRedeemed > 1 ? ` (×${u.quantityRedeemed})` : ''}</li>
                      ))}
                    </ul>
                  </div>
                )}
              </div>
            )}
            <div className="mt-4 flex justify-end">
              <button className="px-4 py-2 rounded bg-red-600 text-white" onClick={() => setAlreadyUsedModal(null)}>OK</button>
            </div>
          </div>
        </div>
      )}

      {/* ── Error modal ──────────────────────────────────────────────────── */}
      {errorModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white rounded shadow-lg max-w-md w-full p-5">
            <h3 className="text-lg font-semibold mb-2 text-red-600">Scan Error</h3>
            <p className="text-sm text-gray-700 mb-3">{errorModal}</p>
            <div className="mt-4 flex justify-end">
              <button className="px-4 py-2 rounded bg-red-600 text-white" onClick={() => setErrorModal(null)}>OK</button>
            </div>
          </div>
        </div>
      )}

      {/* ── Success modal ────────────────────────────────────────────────── */}
      {successModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white rounded-xl shadow-lg max-w-md w-full p-6">
            <h3 className="text-lg font-semibold mb-4 text-green-600">Scan Successful</h3>

            <div className="text-3xl font-bold text-center text-gray-900 mb-2">
              {successModal.optionName}
            </div>

            <div className="text-sm text-center text-gray-600 mb-3">
              #{successModal.ticketId} — {successModal.eventTitle}
            </div>

            {successModal.total > 1 && (
              <div className={`text-center text-sm font-medium mb-4 ${successModal.remaining > 0 ? 'text-amber-600' : 'text-green-700'}`}>
                {successModal.qtyRedeemed} redeemed · {successModal.remaining} remaining of {successModal.total}
              </div>
            )}

            <div className="flex justify-center">
              <button className="px-6 py-2 rounded bg-green-600 text-white" onClick={() => setSuccessModal(null)}>OK</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}