import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { QR_CODE_ID, SCAN_DEBOUNCE_MS, SUCCESSFUL_SCANS_KEY } from '~/constants/checkin'

export const useQRScanner = (
  onQRDetected: (decodedText: string) => void,
  showSnackbar: (title: string, message: string, color: string, icon: string) => void
) => {
  // Scanner state
  const isScanning = ref(false)
  const hasCamera = ref(false)
  const cameraChecking = ref(true)
  const cameraReady = ref(false)
  let html5QrCode: any = null
  const qrCodeId = QR_CODE_ID
  let lastScannedQR: string | null = null
  let lastScanTime: number = 0
  let isProcessing = false // Flag untuk mencegah pemrosesan berulang

  // Daftar QR code yang sudah berhasil di-scan (untuk mencegah double antrian)
  const successfulScans = ref<Set<string>>(new Set())

  // Detect mobile device
  const isMobile = ref(false)
  if (typeof window !== 'undefined') {
    isMobile.value = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || 
                     (window.innerWidth <= 768)
  }

  // Load successful scans dari localStorage
  const loadSuccessfulScans = () => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(SUCCESSFUL_SCANS_KEY)
      if (stored) {
        try {
          const scansArray = JSON.parse(stored)
          successfulScans.value = new Set(scansArray)
        } catch (e) {
          console.error('Error loading successful scans:', e)
          successfulScans.value = new Set()
        }
      }
    }
  }

  // Simpan successful scan ke localStorage
  const saveSuccessfulScan = (qrData: string) => {
    if (typeof window !== 'undefined') {
      successfulScans.value.add(qrData)
      const scansArray = Array.from(successfulScans.value)
      localStorage.setItem(SUCCESSFUL_SCANS_KEY, JSON.stringify(scansArray))
    }
  }

  // Cek apakah QR code sudah pernah berhasil di-scan
  const isQRCodeAlreadyScanned = (qrData: string): boolean => {
    return successfulScans.value.has(qrData)
  }

  // Check camera availability
  const checkCameraAvailability = async () => {
    cameraChecking.value = true
    hasCamera.value = false
    
    // Check if browser supports mediaDevices
    if (typeof navigator === 'undefined' || !navigator.mediaDevices) {
      console.error('navigator.mediaDevices is not supported')
      showSnackbar('Error', 'Browser tidak mendukung akses kamera. Pastikan menggunakan HTTPS atau localhost.', 'error', 'mdi-camera-off')
      cameraChecking.value = false
      return
    }

    try {
      // First, request permission by trying to get user media
      // This is required for enumerateDevices to return device labels
      const stream = await navigator.mediaDevices.getUserMedia({ video: true })
      
      // Stop the stream immediately after getting permission
      stream.getTracks().forEach(track => track.stop())
      
      // Now enumerate devices (will have labels after permission granted)
      const devices = await navigator.mediaDevices.enumerateDevices()
      const videoDevices = devices.filter(device => device.kind === 'videoinput')
      
      hasCamera.value = videoDevices.length > 0
      
      if (hasCamera.value) {
        console.log(`Found ${videoDevices.length} camera(s):`, videoDevices.map(d => d.label || d.deviceId))
      } else {
        console.warn('No video input devices found')
        showSnackbar('Warning', 'Tidak ada kamera yang terdeteksi', 'warning', 'mdi-camera-off')
      }
    } catch (err: any) {
      console.error('Error checking camera:', err)
      hasCamera.value = false
      
      let errorMessage = 'Gagal mengakses kamera. '
      if (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError') {
        errorMessage += 'Izin kamera ditolak. Mohon izinkan akses kamera di pengaturan browser.'
      } else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
        errorMessage += 'Tidak ada kamera yang ditemukan.'
      } else if (err.name === 'NotReadableError' || err.name === 'TrackStartError') {
        errorMessage += 'Kamera sedang digunakan aplikasi lain.'
      } else if (err.name === 'OverconstrainedError' || err.name === 'ConstraintNotSatisfiedError') {
        errorMessage += 'Kamera tidak memenuhi persyaratan.'
      } else {
        errorMessage += `Error: ${err.message || err.name}`
      }
      
      showSnackbar('Error', errorMessage, 'error', 'mdi-camera-off')
    } finally {
      cameraChecking.value = false
    }
  }

  // Test camera function for debugging
  const testCamera = async () => {
    try {
      showSnackbar('Info', 'Menguji akses kamera...', 'info', 'mdi-camera')
      
      if (typeof navigator === 'undefined') {
        showSnackbar('Error', 'navigator is undefined - pastikan di browser, bukan SSR', 'error', 'mdi-alert')
        return
      }
      
      if (!navigator.mediaDevices) {
        showSnackbar('Error', 'navigator.mediaDevices is undefined - pastikan menggunakan HTTPS atau localhost', 'error', 'mdi-alert')
        return
      }
      
      if (!navigator.mediaDevices.getUserMedia) {
        showSnackbar('Error', 'getUserMedia is not supported', 'error', 'mdi-alert')
        return
      }
      
      const stream = await navigator.mediaDevices.getUserMedia({ 
        video: {
          facingMode: 'user',
          width: { ideal: 640 },
          height: { ideal: 480 }
        } 
      })
      
      showSnackbar('Success', 'Kamera berhasil diakses!', 'success', 'mdi-check-circle')
      
      // Stop stream after 2 seconds
      setTimeout(() => {
        stream.getTracks().forEach(track => track.stop())
      }, 2000)
      
    } catch (err: any) {
      console.error('Test camera error:', err)
      let errorMsg = `Error: ${err.name || 'Unknown'}`
      if (err.message) errorMsg += ` - ${err.message}`
      showSnackbar('Error', errorMsg, 'error', 'mdi-alert')
    }
  }

  // Handle QR scan success
  const handleQRScanSuccess = (decodedText: string) => {
    // Validasi data QR - cek di awal sebelum log apapun
    if (!decodedText || decodedText.trim() === '') {
      return // Silent return untuk empty QR code
    }
    
    // Cegah pemrosesan berulang jika sedang memproses
    if (isProcessing) {
      return // Silent return untuk mencegah spam log
    }
    
    // Debounce: cegah scan berulang dalam waktu singkat - cek sebelum log
    const now = Date.now()
    if (lastScannedQR === decodedText && (now - lastScanTime) < SCAN_DEBOUNCE_MS) {
      return // Silent return untuk debounce
    }
    
    // Cek apakah QR code sudah pernah berhasil di-scan (mencegah double antrian)
    if (isQRCodeAlreadyScanned(decodedText)) {
      console.log('⏭️ Scan diabaikan: QR code sudah pernah berhasil di-scan')
      showSnackbar('Peringatan', 'QR Code ini sudah pernah berhasil di-scan. Tidak dapat digunakan lagi untuk mencegah double antrian.', 'warning', 'mdi-alert-circle')
      return
    }
    
    // Set flag processing dan update last scan info
    isProcessing = true
    lastScannedQR = decodedText
    lastScanTime = now
    
    console.log('🎯 QR Scan Success! Data:', decodedText)
    
    // Scanner tetap berjalan untuk memungkinkan scan QR code berikutnya
    
    // Proses data QR melalui callback
    try {
      onQRDetected(decodedText)
    } catch (error) {
      console.error('Error processing QR data:', error)
      showSnackbar('Error', 'Gagal memproses data QR Code', 'error', 'mdi-alert')
    } finally {
      // Reset flag setelah selesai memproses (dengan delay kecil untuk memastikan callback selesai)
      setTimeout(() => {
        isProcessing = false
      }, SCAN_DEBOUNCE_MS)
    }
  }

  // QR Scanner Functions
  const startScanning = async () => {
    // Check camera first
    if (!hasCamera.value) {
      await checkCameraAvailability()
      if (!hasCamera.value) {
        showSnackbar('Error', 'Kamera tidak tersedia. Silakan gunakan input manual atau pastikan kamera terhubung.', 'error', 'mdi-camera-off')
        return
      }
    }

    try {
      // Set scanning state first to render the element
      isScanning.value = true
      
      // Wait for DOM to update and element to be rendered
      await nextTick()
      
      // Wait a bit more to ensure element is fully rendered
      await new Promise(resolve => setTimeout(resolve, 100))
      
      // Check if element exists
      const qrElement = document.getElementById(qrCodeId)
      if (!qrElement) {
        console.error(`Element with id "${qrCodeId}" not found in DOM`)
        isScanning.value = false
        showSnackbar('Error', 'Element scanner tidak ditemukan. Silakan refresh halaman.', 'error', 'mdi-alert')
        return
      }
      
      // Dynamic import html5-qrcode
      if (!html5QrCode) {
        const { Html5Qrcode: Html5QrcodeClass } = await import('html5-qrcode')
        html5QrCode = new Html5QrcodeClass(qrCodeId)
        console.log('Html5Qrcode initialized')
      }

      if (html5QrCode) {
        cameraReady.value = false
        
        // Konfigurasi kamera untuk mobile dan desktop
        const cameraConfig = isMobile.value 
          ? { facingMode: "environment" } // Mobile: gunakan kamera belakang
          : { facingMode: "user" } // Desktop: gunakan kamera depan (webcam)
        
        // Video constraints yang lebih fleksibel
        const baseVideoConstraints = isMobile.value
          ? {
              facingMode: "environment",
              width: { ideal: 640, min: 320 },
              height: { ideal: 480, min: 240 }
            }
          : {
              facingMode: "user",
              width: { ideal: 1280, min: 640 },
              height: { ideal: 720, min: 480 }
            }
        
        // Tambahkan advanced constraints hanya jika didukung
        const videoConstraints: any = { ...baseVideoConstraints }
        
        console.log('Starting QR scanner with config:', {
          isMobile: isMobile.value,
          cameraConfig,
          videoConstraints
        })
        
        try {
          await html5QrCode.start(
            cameraConfig,
            {
              fps: isMobile.value ? 15 : 20, // FPS optimal untuk deteksi
              qrbox: function(viewfinderWidth: number, viewfinderHeight: number) {
                // QR box dengan ukuran lebih besar untuk deteksi lebih mudah
                const minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight)
                // Gunakan 80-90% dari viewfinder untuk area scanning yang lebih besar
                const percentageSize = Math.floor(minEdgeSize * 0.80)
                // Atau ukuran tetap yang lebih besar
                const fixedSize = isMobile.value ? 250 : 250
                // Gunakan yang lebih besar antara percentage atau fixed
                const qrboxSize = Math.max(percentageSize, fixedSize)
                
                // Pastikan tidak melebihi viewfinder
                const finalSize = Math.min(qrboxSize, minEdgeSize * 0.80)
                
                console.log('QR Box size:', finalSize, 'Viewfinder:', viewfinderWidth, 'x', viewfinderHeight)
                
                return {
                  width: Math.max(finalSize, 250), // Minimum 250px untuk deteksi lebih baik
                  height: Math.max(finalSize, 250)
                }
              },
              aspectRatio: 1.0,
              disableFlip: false,
              videoConstraints: videoConstraints,
              rememberLastUsedCamera: true,
              showTorchButtonIfSupported: true,
              // Tambahkan opsi untuk meningkatkan deteksi
              verbose: false // Set true untuk debugging
            },
            (decodedText: string, decodedResult: any) => {
              // QR Code berhasil di-scan
              console.log('✅ QR Code detected:', decodedText)
              console.log('📊 Decoded result:', decodedResult)
              
              // Validasi dan proses QR code
              if (decodedText && decodedText.trim() !== '') {
                handleQRScanSuccess(decodedText)
              } else {
                console.warn('Empty QR code detected')
              }
            },
            (errorMessage: string) => {
              // Log error untuk debugging - hanya log error penting
              // Error ini biasanya muncul terus menerus saat tidak ada QR code yang terdeteksi
              // Jadi kita filter untuk menghindari spam console
              if (errorMessage) {
                // Filter out common non-critical errors
                const isCriticalError = !errorMessage.includes('NotFoundException') && 
                                       !errorMessage.includes('No QR') &&
                                       !errorMessage.includes('QR code parse error') &&
                                       !errorMessage.includes('QR code parse error, error') &&
                                       !errorMessage.includes('QR code decode error')
                
                if (isCriticalError) {
                  console.warn('QR Scanner warning:', errorMessage)
                }
              }
            }
          )
          
          // Set camera ready setelah sedikit delay untuk memastikan video sudah dimuat
          setTimeout(() => {
            cameraReady.value = true
            console.log('Camera ready, scanner is active')
          }, 500)
          
          showSnackbar('Info', 'Scanner aktif. Arahkan kamera ke QR code dan pastikan pencahayaan cukup', 'info', 'mdi-camera')
        } catch (cameraError: any) {
          console.error('Camera error:', cameraError)
          
          // Jika kamera belakang tidak tersedia di mobile, coba kamera depan
          if (isMobile.value && cameraError.name === 'NotFoundError') {
            try {
              console.log('Trying front camera as fallback...')
              await html5QrCode.start(
                { facingMode: "user" },
                {
                  fps: 15,
                  qrbox: function(viewfinderWidth: number, viewfinderHeight: number) {
                    const minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight)
                    const percentageSize = Math.floor(minEdgeSize * 0.85)
                    const fixedSize = 300
                    const qrboxSize = Math.max(percentageSize, fixedSize)
                    const finalSize = Math.min(qrboxSize, minEdgeSize * 0.95)
                    
                    return {
                      width: Math.max(finalSize, 250),
                      height: Math.max(finalSize, 250)
                    }
                  },
                  aspectRatio: 1.0,
                  disableFlip: false,
                  videoConstraints: {
                    facingMode: "user",
                    width: { ideal: 640, min: 320 },
                    height: { ideal: 480, min: 240 }
                  },
                  rememberLastUsedCamera: true,
                  verbose: false
                },
                (decodedText: string, decodedResult: any) => {
                  console.log('✅ QR Code detected (front camera):', decodedText)
                  if (decodedText && decodedText.trim() !== '') {
                    handleQRScanSuccess(decodedText)
                  }
                },
                (errorMessage: string) => {
                  if (errorMessage) {
                    const isCriticalError = !errorMessage.includes('NotFoundException') && 
                                           !errorMessage.includes('No QR') &&
                                           !errorMessage.includes('QR code parse error') &&
                                           !errorMessage.includes('QR code decode error')
                    
                    if (isCriticalError) {
                      console.warn('QR Scanner (front) warning:', errorMessage)
                    }
                  }
                }
              )
              
              setTimeout(() => {
                cameraReady.value = true
              }, 500)
              
              showSnackbar('Info', 'Menggunakan kamera depan. Arahkan QR code ke kamera', 'info', 'mdi-camera')
            } catch (fallbackError: any) {
              console.error('Fallback camera also failed:', fallbackError)
              throw cameraError // Throw original error
            }
          } else {
            // Coba menggunakan deviceId langsung jika facingMode gagal
            try {
              console.log('Trying to get camera devices...')
              const devices = await navigator.mediaDevices.enumerateDevices()
              const videoDevices = devices.filter(device => device.kind === 'videoinput')
              
              if (videoDevices.length > 0) {
                // Gunakan kamera pertama yang tersedia
                const deviceId = videoDevices[0].deviceId
                console.log('Using device:', deviceId, videoDevices[0].label)
                
                await html5QrCode.start(
                  { deviceId: { exact: deviceId } },
                  {
                    fps: isMobile.value ? 15 : 20,
                    qrbox: function(viewfinderWidth: number, viewfinderHeight: number) {
                      const minEdgeSize = Math.min(viewfinderWidth, viewfinderHeight)
                      const percentageSize = Math.floor(minEdgeSize * 0.80)
                      const fixedSize = isMobile.value ? 300 : 400
                      const qrboxSize = Math.max(percentageSize, fixedSize)
                      const finalSize = Math.min(qrboxSize, minEdgeSize * 0.80)
                      
                      return {
                        width: Math.max(finalSize, 250),
                        height: Math.max(finalSize, 250)
                      }
                    },
                    aspectRatio: 1.0,
                    disableFlip: false,
                    videoConstraints: {
                      deviceId: { exact: deviceId },
                      width: { ideal: isMobile.value ? 640 : 1280, min: isMobile.value ? 320 : 640 },
                      height: { ideal: isMobile.value ? 480 : 720, min: isMobile.value ? 240 : 480 }
                    },
                    rememberLastUsedCamera: true,
                    verbose: false
                  },
                  (decodedText: string, decodedResult: any) => {
                    console.log('✅ QR Code detected (deviceId):', decodedText)
                    if (decodedText && decodedText.trim() !== '') {
                      handleQRScanSuccess(decodedText)
                    }
                  },
                  (errorMessage: string) => {
                    if (errorMessage) {
                      const isCriticalError = !errorMessage.includes('NotFoundException') && 
                                             !errorMessage.includes('No QR') &&
                                             !errorMessage.includes('QR code parse error') &&
                                             !errorMessage.includes('QR code decode error')
                      
                      if (isCriticalError) {
                        console.warn('QR Scanner (deviceId) warning:', errorMessage)
                      }
                    }
                  }
                )
                
                setTimeout(() => {
                  cameraReady.value = true
                }, 500)
                
                showSnackbar('Info', 'Scanner aktif menggunakan kamera yang tersedia', 'info', 'mdi-camera')
              } else {
                throw cameraError
              }
            } catch (deviceError: any) {
              console.error('DeviceId approach also failed:', deviceError)
              throw cameraError
            }
          }
        }
      }
    } catch (err: any) {
      console.error('Error starting scanner:', err)
      isScanning.value = false
      cameraReady.value = false
      
      // Don't set hasCamera to false if it was detected, just log the error
      let errorMessage = 'Gagal memulai scanner. '
      
      if (err.message && err.message.includes('not found')) {
        errorMessage = 'Element scanner tidak ditemukan. Silakan refresh halaman dan coba lagi.'
        console.error('Element not found error. Element ID:', qrCodeId)
      } else if (err.name === 'NotAllowedError') {
        errorMessage = 'Akses kamera ditolak. Mohon izinkan akses kamera di pengaturan browser.'
      } else if (err.name === 'NotFoundError') {
        errorMessage = 'Kamera tidak ditemukan. Silakan gunakan input manual.'
        hasCamera.value = false
      } else if (err.name === 'NotReadableError') {
        errorMessage = 'Kamera sedang digunakan aplikasi lain. Tutup aplikasi lain yang menggunakan kamera.'
      } else {
        errorMessage += err.message || err.name || 'Unknown error'
      }
      
      showSnackbar('Error', errorMessage, 'error', 'mdi-alert')
    }
  }

  const stopScanning = async () => {
    const scannerInstance = html5QrCode
    
    // Reset state immediately to update UI
    isScanning.value = false
    cameraReady.value = false
    
    // Clear reference immediately to prevent re-entry
    html5QrCode = null
    
    // If no instance, nothing to clean up
    if (!scannerInstance) {
      return
    }
    
    try {
      // Stop the scanner (this stops the camera stream)
      if (typeof scannerInstance.stop === 'function') {
        await scannerInstance.stop().catch((err: any) => {
          // Ignore stop errors - scanner might already be stopped
          console.warn('Scanner stop error (ignored):', err?.message || err)
        })
      }
    } catch (err: any) {
      // Ignore errors from stop
      console.warn('Error stopping scanner (ignored):', err?.message || err)
    }
    
    try {
      // Clear the scanner (this cleans up DOM and resources)
      // Only try to clear if stop was successful or if clear method exists
      if (typeof scannerInstance.clear === 'function') {
        await scannerInstance.clear().catch((err: any) => {
          // Ignore clear errors - DOM might already be cleaned up
          console.warn('Scanner clear error (ignored):', err?.message || err)
        })
      }
    } catch (err: any) {
      // Ignore errors from clear
      console.warn('Error clearing scanner (ignored):', err?.message || err)
    }
    
    // Show notification after cleanup attempts
    try {
      showSnackbar('Info', 'Scanner dihentikan', 'info', 'mdi-camera-off')
    } catch (e) {
      // Ignore snackbar errors
    }
  }

  // Initialize on mount
  if (typeof window !== 'undefined') {
    loadSuccessfulScans()
  }

  return {
    // State
    isScanning,
    hasCamera,
    cameraChecking,
    cameraReady,
    // Functions
    checkCameraAvailability,
    testCamera,
    startScanning,
    stopScanning,
    saveSuccessfulScan,
    isQRCodeAlreadyScanned,
  }
}
