'use client';

import { useState, useRef, useEffect, useCallback } from 'react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { QrCode, Camera, RotateCcw, CheckCircle, XCircle, User, MapPin, Clock, Train, CameraOff } from 'lucide-react';
import { ticketsApi, apiClient } from '@/lib/api';
import { useAuthStore } from '@/lib/auth-store';
import { formatDateTime } from '@/lib/utils';
import { useRouter } from 'next/navigation';
import Header from '@/components/layout/Header';

// Add QR Scanner component
function QRScanner({ onScan, onError }: { onScan: (data: string) => void; onError: (error: string) => void }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isScanning, setIsScanning] = useState(false);
  const [isInitializing, setIsInitializing] = useState(false);
  const streamRef = useRef<MediaStream | null>(null);
  const [cameraError, setCameraError] = useState<string | null>(null);
  const scanIntervalRef = useRef<number | null>(null);

  const startCamera = async () => {
    try {
      setIsInitializing(true);
      setCameraError(null);
      
      // Check if mediaDevices is supported
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        const errorMsg = 'Camera not supported in this browser. Please use a modern browser like Chrome, Firefox, or Safari.';
        setCameraError(errorMsg);
        onError(errorMsg);
        setIsInitializing(false);
        return;
      }

      // First, stop any existing stream
      if (streamRef.current) {
        streamRef.current.getTracks().forEach(track => track.stop());
        streamRef.current = null;
      }

      // Request camera access with simpler fallback
      let mediaStream: MediaStream | null = null;
      
      try {
        // Try with environment (back) camera first
        mediaStream = await navigator.mediaDevices.getUserMedia({
          video: { 
            facingMode: 'environment',
            width: { ideal: 1280 },
            height: { ideal: 720 }
          },
          audio: false
        });
      } catch {
        // Fallback to any available camera with simple constraints
        try {
          mediaStream = await navigator.mediaDevices.getUserMedia({
            video: true,
            audio: false
          });
        } catch (fallbackErr) {
          throw fallbackErr;
        }
      }
      
      if (!mediaStream) {
        throw new Error('Failed to get media stream');
      }

      if (!videoRef.current) {
        throw new Error('Video element not found');
      }

      const video = videoRef.current;
      video.srcObject = mediaStream;
      
      // Wait for video to be ready with proper event handling
      await new Promise<void>((resolve, reject) => {
        let resolved = false;
        
        const cleanup = () => {
          video.removeEventListener('loadedmetadata', onLoadedMetadata);
          video.removeEventListener('loadeddata', onLoadedData);
          video.removeEventListener('canplay', onCanPlay);
          video.removeEventListener('error', onVideoError);
        };
        
        const finishResolve = () => {
          if (!resolved) {
            resolved = true;
            cleanup();
            resolve();
          }
        };
        
        const onLoadedMetadata = () => finishResolve();
        const onLoadedData = () => finishResolve();
        const onCanPlay = () => finishResolve();
        
        const onVideoError = (_e: Event) => {
          cleanup();
          reject(new Error('Video failed to load'));
        };
        
        // Add multiple event listeners for better compatibility
        video.addEventListener('loadedmetadata', onLoadedMetadata);
        video.addEventListener('loadeddata', onLoadedData);
        video.addEventListener('canplay', onCanPlay);
        video.addEventListener('error', onVideoError);
        
        setTimeout(() => finishResolve(), 2000);
      });
      
      try {
        await video.play();
      } catch {
        await new Promise(resolve => setTimeout(resolve, 100));
        try { await video.play(); } catch { /* continue */ }
      }
      
      // Set state to show video
      streamRef.current = mediaStream;
      setIsScanning(true);
      setIsInitializing(false);
      
    } catch (error: any) {
      
      let errorMsg = 'Camera access failed. Please check permissions and try again.';
      
      if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
        errorMsg = 'Camera permission denied. Please allow camera access in your browser settings and try again.';
      } else if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
        errorMsg = 'No camera found. Please connect a camera and try again.';
      } else if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
        errorMsg = 'Camera is already in use by another application. Please close other apps using the camera.';
      } else if (error.name === 'OverconstrainedError') {
        errorMsg = 'Camera does not meet the requirements. Please try a different camera.';
      } else if (error.name === 'SecurityError') {
        errorMsg = 'Camera access blocked due to security settings. Please use HTTPS or check your browser security settings.';
      }
      
      setCameraError(errorMsg);
      onError(errorMsg);
      
      // Clean up on error
      if (streamRef.current) {
        streamRef.current.getTracks().forEach(track => track.stop());
        streamRef.current = null;
      }
      setIsScanning(false);
      setIsInitializing(false);
    }
  };

  const stopCamera = useCallback(() => {
    if (scanIntervalRef.current) {
      clearInterval(scanIntervalRef.current);
      scanIntervalRef.current = null;
    }
    if (streamRef.current) {
      streamRef.current.getTracks().forEach(track => track.stop());
      streamRef.current = null;
    }
    if (videoRef.current) {
      videoRef.current.srcObject = null;
    }
    setIsScanning(false);
    setCameraError(null);
  }, []);

  // QR code scanning with jsqr
  const scanFrame = useCallback(() => {
    if (!videoRef.current || !canvasRef.current || !isScanning) return;
    
    const video = videoRef.current;
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    
    if (ctx && video.readyState === video.HAVE_ENOUGH_DATA) {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      
      try {
        const jsQR = (window as any).jsQR;
        if (jsQR) {
          const code = jsQR(imageData.data, imageData.width, imageData.height, {
            inversionAttempts: 'dontInvert',
          });
          if (code) {
            onScan(code.data);
            stopCamera();
          }
        }
      } catch { /* ignore scan errors */ }
    }
  }, [isScanning, onScan, stopCamera]);

  useEffect(() => {
    if (isScanning) {
      scanIntervalRef.current = window.setInterval(scanFrame, 100);
    } else {
      if (scanIntervalRef.current) {
        clearInterval(scanIntervalRef.current);
        scanIntervalRef.current = null;
      }
    }
  }, [isScanning, scanFrame]);

  // Cleanup on unmount only
  useEffect(() => {
    return () => stopCamera();
  }, [stopCamera]);

  // Load jsqr from CDN
  useEffect(() => {
    if (!(window as any).jsQR) {
      const script = document.createElement('script');
      script.src = 'https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js';
      script.async = true;
      document.body.appendChild(script);
      return () => {
        document.body.removeChild(script);
      };
    }
  }, []);

  return (
    <div className="space-y-4">
      {/* Video viewer - always rendered, visibility controlled by display style */}
      <div className={`space-y-3 ${!isScanning ? '!hidden' : ''}`}>
        <div className="relative bg-black rounded-xl overflow-hidden" style={{ minHeight: '320px' }}>
          <video
            ref={videoRef}
            autoPlay
            playsInline
            muted
            className="w-full min-h-[320px] object-cover block"
            style={{ display: 'block', visibility: 'visible' }}
          />
          <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
            <div className="relative w-48 h-48">
              <div className="absolute inset-0 border-2 border-white border-dashed rounded-lg animate-pulse"></div>
              <div className="absolute top-0 left-0 w-6 h-6 border-t-4 border-l-4 border-blue-400 rounded-tl-lg"></div>
              <div className="absolute top-0 right-0 w-6 h-6 border-t-4 border-r-4 border-blue-400 rounded-tr-lg"></div>
              <div className="absolute bottom-0 left-0 w-6 h-6 border-b-4 border-l-4 border-blue-400 rounded-bl-lg"></div>
              <div className="absolute bottom-0 right-0 w-6 h-6 border-b-4 border-r-4 border-blue-400 rounded-br-lg"></div>
            </div>
          </div>
          <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4 pointer-events-none">
            <p className="text-white text-center text-sm font-medium">Position QR code within frame</p>
            <p className="text-white/70 text-center text-xs mt-1">Scanning...</p>
          </div>
        </div>
        <canvas ref={canvasRef} className="hidden" />
        <button
          onClick={stopCamera}
          className="w-full bg-gray-600 hover:bg-gray-700 text-white font-semibold py-3 px-6 rounded-xl transition-colors flex items-center justify-center gap-2"
        >
          <CameraOff className="w-5 h-5" />
          Stop Camera
        </button>
      </div>
      
      {/* Start button and loading state */}
      {!isScanning && !isInitializing && (
        <div className="space-y-3">
          <button
            onClick={startCamera}
            className="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-4 px-6 rounded-xl transition-colors flex items-center justify-center gap-2"
          >
            <Camera className="w-5 h-5" />
            Scan QR Code
          </button>
          {cameraError && (
            <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-3">
              <p className="text-red-700 dark:text-red-300 text-sm">{cameraError}</p>
            </div>
          )}
        </div>
      )}
      
      {/* Loading state */}
      {isInitializing && (
        <div className="space-y-3">
          <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-xl p-6">
            <div className="flex flex-col items-center justify-center space-y-3">
              <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
              <p className="text-blue-700 dark:text-blue-300 font-medium">Starting camera...</p>
              <p className="text-blue-600 dark:text-blue-400 text-sm text-center">
                Please allow camera access when prompted by your browser
              </p>

            </div>
          </div>
          <button
            onClick={() => {
              if (streamRef.current) {
                streamRef.current.getTracks().forEach(track => track.stop());
                streamRef.current = null;
              }
              setIsInitializing(false);
              setCameraError('Camera initialization cancelled by user');
            }}
            className="w-full bg-gray-500 hover:bg-gray-600 text-white font-semibold py-3 px-6 rounded-xl transition-colors"
          >
            Cancel
          </button>
        </div>
      )}
    </div>
  );
}

export default function BoardingPage() {
  const [qrInput, setQrInput] = useState('');
  const [lastScanned, setLastScanned] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [isScanning, setIsScanning] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const { user, isAuthenticated } = useAuthStore();
  const router = useRouter();

  // Check authentication on mount
  useEffect(() => {
    if (!isAuthenticated) {
      router.push('/login');
      return;
    }
  }, [isAuthenticated, router]);

  // Get current agent data
  const { data: agentData } = useQuery({
    queryKey: ['agent-me'],
    queryFn: () => apiClient.get<any>('/agents/me'),
    enabled: !!user,
    retry: false,
  });

  const boardingMutation = useMutation({
    mutationFn: (qrCodeOrRef: string) => 
      ticketsApi.scanAndBoard(qrCodeOrRef, {
        validatorId: agentData?.id || user?.id || 'BACKOFFICE',
        gateId: 'MOBILE-GATE',
      }),
    onSuccess: (result) => {
      setError(null);
      if (result.success) {
        setSuccess('Passenger boarded successfully!');
        setLastScanned(result.boarding);
        setQrInput(result.boarding?.ticketNumber || result.boarding?.bookingRef || '');
        // Auto-focus for next scan
        setTimeout(() => inputRef.current?.focus(), 1000);
      } else {
        setError(result.error || 'Boarding failed');
        setLastScanned(null);
      }
    },
    onError: (error: any) => {
      setError(error?.response?.data?.message || error.message || 'Boarding failed');
      setSuccess(null);
      setLastScanned(null);
    },
  });

  const handleScan = (inputValue?: string) => {
    const valueToScan = inputValue || qrInput.trim();
    if (!valueToScan) {
      setError('Please enter QR code or booking reference');
      return;
    }
    
    setError(null);
    setSuccess(null);
    boardingMutation.mutate(valueToScan);
  };

  const handleButtonClick = () => {
    handleScan();
  };

  const handleKeyPress = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter') {
      handleButtonClick();
    }
  };

  const clearAll = () => {
    setQrInput('');
    setError(null);
    setSuccess(null);
    setLastScanned(null);
    inputRef.current?.focus();
  };

  useEffect(() => {
    // Auto-focus on mount for mobile scanning (only if authenticated)
    if (isAuthenticated) {
      inputRef.current?.focus();
    }
  }, [isAuthenticated]);

  // Show loading or redirect if not authenticated
  if (!isAuthenticated) {
    return (
      <div className="flex h-screen items-center justify-center bg-gray-50 dark:bg-slate-950">
        <div className="text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-edr-green-600 mx-auto"></div>
          <p className="mt-4 text-gray-600 dark:text-gray-400">Redirecting to login...</p>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-screen overflow-hidden bg-gray-50 dark:bg-slate-950">
      <div className="flex flex-1 flex-col overflow-hidden">
        <Header />
        <main className="flex-1 overflow-y-auto bg-gray-50 dark:bg-slate-950">
          <div className="min-h-full bg-gradient-to-br from-emerald-50 to-blue-50 dark:from-slate-900 dark:to-slate-800 p-4">
            {/* Mobile-optimized container */}
            <div className="max-w-md mx-auto space-y-6">
        
        {/* Header */}
        <div className="text-center py-6">
          <div className="inline-flex items-center justify-center w-16 h-16 bg-emerald-600 rounded-full mb-4">
            <QrCode className="w-8 h-8 text-white" />
          </div>
          <h1 className="text-2xl font-bold text-gray-900 dark:text-white">Boarding</h1>
          <p className="text-gray-600 dark:text-gray-400 mt-1">Scan ticket QR codes to board passengers</p>
          {agentData && (
            <div className="text-sm text-emerald-600 dark:text-emerald-400 mt-2">
              Agent: {agentData.agentCode || agentData.name}
            </div>
          )}
        </div>

        {/* Scanner Input */}
        <div className="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6 border border-gray-100 dark:border-slate-700">
          <div className="space-y-4">
            
            {/* Camera Scanner */}
            <QRScanner 
              onScan={(data) => {
                let displayValue = data;
                try {
                  const parsed = JSON.parse(data);
                  if (parsed.ticketNumber) displayValue = parsed.ticketNumber;
                  else if (parsed.ref) displayValue = parsed.ref;
                } catch { /* not JSON, use raw */ }
                setQrInput(displayValue);
                handleScan(data);
              }}
              onError={setError}
            />
            
            {/* Manual Input */}
            <div className="text-center text-gray-500 dark:text-gray-400 text-sm">OR</div>
            
            <div className="relative">
              <input
                ref={inputRef}
                type="text"
                value={qrInput}
                onChange={(e) => setQrInput(e.target.value)}
                onKeyPress={handleKeyPress}
                placeholder="Type ticket number"
                className="w-full px-4 py-4 text-lg border border-gray-300 dark:border-slate-600 rounded-xl 
                         focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 
                         dark:bg-slate-700 dark:text-white dark:placeholder-slate-400
                         font-mono tracking-wide"
                autoCapitalize="characters"
                autoComplete="off"
                autoFocus
              />
            </div>

            <div className="flex gap-3">
              <button
                onClick={handleButtonClick}
                disabled={boardingMutation.isPending || !qrInput.trim()}
                className="flex-1 bg-emerald-600 hover:bg-emerald-700 disabled:bg-gray-300 
                         text-white font-semibold py-4 px-6 rounded-xl transition-colors
                         disabled:cursor-not-allowed text-lg"
              >
                {boardingMutation.isPending ? 'Boarding...' : 'Board Passenger'}
              </button>
              
              <button
                onClick={clearAll}
                className="bg-gray-500 hover:bg-gray-600 text-white font-semibold py-4 px-6 rounded-xl transition-colors"
              >
                <RotateCcw className="w-5 h-5" />
              </button>
            </div>
          </div>
        </div>

        {/* Success Message */}
        {success && (
          <div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-2xl p-6">
            <div className="flex items-center gap-3 mb-3">
              <CheckCircle className="w-6 h-6 text-green-600 dark:text-green-400" />
              <span className="text-green-800 dark:text-green-200 font-semibold text-lg">{success}</span>
            </div>
            
            {lastScanned && (
              <div className="mt-4 space-y-3">
                <div className="flex items-center gap-2">
                  <User className="w-4 h-4 text-green-600 dark:text-green-400" />
                  <span className="text-green-700 dark:text-green-300 font-medium">
                    {lastScanned.passengerName}
                  </span>
                </div>
                
                <div className="flex items-center gap-2">
                  <MapPin className="w-4 h-4 text-green-600 dark:text-green-400" />
                  <span className="text-green-700 dark:text-green-300">
                    {lastScanned.route}
                  </span>
                </div>
                
                <div className="flex items-center gap-2">
                  <Train className="w-4 h-4 text-green-600 dark:text-green-400" />
                  <span className="text-green-700 dark:text-green-300">
                    {lastScanned.trainName} - Coach {lastScanned.coach}, Seat {lastScanned.seat}
                  </span>
                </div>
                
                <div className="flex items-center gap-2">
                  <Clock className="w-4 h-4 text-green-600 dark:text-green-400" />
                  <span className="text-green-700 dark:text-green-300">
                    Boarded: {formatDateTime(lastScanned.boardedAt)} ({lastScanned.leg})
                  </span>
                </div>
                
                {lastScanned.isRoundTrip && (
                  <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3 mt-3">
                    <p className="text-blue-700 dark:text-blue-300 text-sm">
                      ℹ️ Round-trip ticket: Scan again for return journey
                    </p>
                  </div>
                )}
                
                <div className="text-sm text-green-600 dark:text-green-400 font-mono mt-2">
                  Booking: {lastScanned.bookingRef} | Ticket: {lastScanned.ticketNumber}
                </div>
                
                <div className="text-xs text-green-600 dark:text-green-400 mt-2">
                  📧 Email & SMS notifications sent to passenger
                </div>
              </div>
            )}
          </div>
        )}

        {/* Error Message */}
        {error && (
          <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-2xl p-6">
            <div className="flex items-center gap-3">
              <XCircle className="w-6 h-6 text-red-600 dark:text-red-400" />
              <span className="text-red-800 dark:text-red-200 font-semibold">{error}</span>
            </div>
          </div>
        )}

        {/* Instructions */}
        <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-2xl p-6">
          <h3 className="text-blue-800 dark:text-blue-200 font-semibold mb-3">How to scan:</h3>
          <ul className="text-blue-700 dark:text-blue-300 space-y-2 text-sm">
            <li>• Tap "Scan QR Code" and point at ticket QR code</li>
            <li>• Allow camera access when your browser prompts you</li>
            <li>• Hold phone steady and position QR code within the frame</li>
            <li>• For manual option, type or paste ticket number</li>
            <li>• Tickets can only be boarded on their departure date</li>
            <li>• First scan boards outbound leg for round trips</li>
            <li>• Email & SMS sent automatically to passenger contacts</li>
            <li>• Red error shows validation issues</li>
          </ul>
          <div className="mt-3 pt-3 border-t border-blue-200 dark:border-blue-700">
            <p className="text-blue-700 dark:text-blue-300 text-xs">
              <strong>Tip:</strong> If camera doesn't open, check browser permissions in Settings → Privacy → Camera
            </p>
          </div>
        </div>

        {/* Quick Stats */}
        <div className="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6 border border-gray-100 dark:border-slate-700">
          <h3 className="text-gray-900 dark:text-white font-semibold mb-3">Session Summary</h3>
          <div className="flex justify-between items-center text-sm">
            <span className="text-gray-600 dark:text-gray-400">Status:</span>
            <span className="text-emerald-600 dark:text-emerald-400 font-semibold">
              Ready to scan
            </span>
          </div>
        </div>

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