import { useState, useRef, useEffect } from 'react'
import { photosApi, PhotoImportRequest } from '../api/photos'
import { jobsApi, JobResponse, JobStatus } from '../api/jobs'

interface JobProgress {
  id: string
  status: string
  progress: number
  message: string
  processed?: number
  total?: number
}

export default function Scan() {
  const [folderPath, setFolderPath] = useState('')
  const [recursive, setRecursive] = useState(true)
  const [isImporting, setIsImporting] = useState(false)
  const [isBrowsing, setIsBrowsing] = useState(false)
  const [currentJob, setCurrentJob] = useState<JobResponse | null>(null)
  const [jobProgress, setJobProgress] = useState<JobProgress | null>(null)
  const [importResult, setImportResult] = useState<{
    added?: number
    existing?: number
    total?: number
  } | null>(null)
  const [error, setError] = useState<string | null>(null)
  const eventSourceRef = useRef<EventSource | null>(null)

  // Cleanup event source on unmount
  useEffect(() => {
    return () => {
      if (eventSourceRef.current) {
        eventSourceRef.current.close()
      }
    }
  }, [])

  const handleFolderBrowse = async () => {
    setIsBrowsing(true)
    setError(null)
    
    // Try backend API first (uses tkinter for native folder picker with full path)
    try {
      console.log('Attempting to open native folder picker...')
      const result = await photosApi.browseFolder()
      console.log('Backend folder picker result:', result)
      
      if (result.success && result.path) {
        // Ensure we have a valid absolute path (not just folder name)
        const path = result.path.trim()
        if (path && path.length > 0) {
          // Verify it looks like an absolute path:
          // - Unix/Linux: starts with / (includes mounted network shares like /mnt/...)
          // - Windows local: starts with drive letter like C:\
          // - Windows UNC: starts with \\ (network paths like \\server\share\folder)
          const isUnixPath = path.startsWith('/')
          const isWindowsLocalPath = /^[A-Za-z]:[\\/]/.test(path)
          const isWindowsUncPath = path.startsWith('\\\\') || path.startsWith('//')
          
          if (isUnixPath || isWindowsLocalPath || isWindowsUncPath) {
            setFolderPath(path)
            setIsBrowsing(false)
            return
          } else {
            // Backend validated it, so trust it even if it doesn't match our patterns
            // (might be a valid path format we didn't account for)
            console.warn('Backend returned path with unexpected format:', path)
            setFolderPath(path)
            setIsBrowsing(false)
            return
          }
        }
      }
      // If we get here, result.success was false or path was empty
      console.warn('Backend folder picker returned no path:', result)
      if (result.success === false && result.message) {
        setError(result.message || 'No folder was selected. Please try again.')
      } else {
        setError('No folder was selected. Please try again.')
      }
      setIsBrowsing(false)
    } catch (err: any) {
      // Backend API failed, fall back to browser picker
      console.warn('Backend folder picker unavailable, using browser fallback:', err)
      
      // Extract error message from various possible locations
      const errorMsg = err?.response?.data?.detail || 
                      err?.response?.data?.message || 
                      err?.message || 
                      String(err) || 
                      ''
      
      console.log('Error details:', {
        status: err?.response?.status,
        detail: err?.response?.data?.detail,
        message: err?.message,
        fullError: err
      })
      
      // Check if it's a display/availability issue
      if (errorMsg.includes('display') || errorMsg.includes('DISPLAY') || errorMsg.includes('tkinter')) {
        // Show user-friendly message about display issue
        setError('Native folder picker unavailable. Using browser fallback.')
      } else if (err?.response?.status === 503) {
        // 503 Service Unavailable - likely tkinter or display issue
        setError('Native folder picker unavailable (tkinter/display issue). Using browser fallback.')
      } else {
        // Other error - log it but continue to browser fallback
        console.error('Error calling backend folder picker:', err)
        setError('Native folder picker unavailable. Using browser fallback.')
      }
    }
    
    // Fallback: Use browser-based folder picker
    // This code runs if backend API failed or returned no path
    console.log('Attempting browser fallback folder picker...')
    
    // Use File System Access API if available (modern browsers)
    if (typeof window !== 'undefined' && 'showDirectoryPicker' in window) {
      try {
        console.log('Using File System Access API...')
        const directoryHandle = await (window as any).showDirectoryPicker()
        // Get the folder name from the handle
        const folderName = directoryHandle.name
        // Note: Browsers don't expose full absolute paths for security reasons
        console.log('Selected folder name:', folderName)
        
        // Browser picker only gives folder name, not full path
        // Set the folder name and show helpful message
        setFolderPath(folderName)
        setError('Browser picker only shows folder name. Please enter the full absolute path manually in the input field above.')
      } catch (err: any) {
        // User cancelled the picker
        if (err.name !== 'AbortError') {
          console.error('Error selecting folder:', err)
          setError('Error opening folder picker: ' + err.message)
        } else {
          // User cancelled - clear any previous error
          setError(null)
        }
      } finally {
        setIsBrowsing(false)
      }
    } else {
      // Fallback: use a hidden directory input
      // Note: This will show a browser confirmation dialog that cannot be removed
      console.log('Using file input fallback...')
      const input = document.createElement('input')
      input.type = 'file'
      input.setAttribute('webkitdirectory', '')
      input.setAttribute('directory', '')
      input.setAttribute('multiple', '')
      input.style.display = 'none'
      
      input.onchange = (e: any) => {
        const files = e.target.files
        if (files && files.length > 0) {
          const firstFile = files[0]
          const relativePath = firstFile.webkitRelativePath
          const pathParts = relativePath.split('/')
          const rootFolder = pathParts[0]
          // Note: Browsers don't expose full absolute paths for security reasons
          console.log('Selected folder name:', rootFolder)
          
          // Browser picker only gives folder name, not full path
          // Set the folder name and show helpful message
          setFolderPath(rootFolder)
          setError('Browser picker only shows folder name. Please enter the full absolute path manually in the input field above.')
        }
        if (document.body.contains(input)) {
          document.body.removeChild(input)
        }
        setIsBrowsing(false)
      }
      
      input.oncancel = () => {
        if (document.body.contains(input)) {
          document.body.removeChild(input)
        }
        setIsBrowsing(false)
      }
      
      document.body.appendChild(input)
      input.click()
    }
  }

  const handleScanFolder = async () => {
    if (!folderPath.trim()) {
      setError('Please enter a folder path')
      return
    }

    setIsImporting(true)
    setError(null)
    setImportResult(null)
    setCurrentJob(null)
    setJobProgress(null)

    try {
      const request: PhotoImportRequest = {
        folder_path: folderPath.trim(),
        recursive,
      }

      const response = await photosApi.importPhotos(request)
      setCurrentJob({
        id: response.job_id,
        status: JobStatus.PENDING,
        progress: 0,
        message: response.message,
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
      })

      // Start SSE stream for job progress
      startJobProgressStream(response.job_id)
    } catch (err: any) {
      setError(err.response?.data?.detail || err.message || 'Import failed')
      setIsImporting(false)
    }
  }

  const startJobProgressStream = (jobId: string) => {
    // Close existing stream if any
    if (eventSourceRef.current) {
      eventSourceRef.current.close()
    }

    const eventSource = photosApi.streamJobProgress(jobId)
    eventSourceRef.current = eventSource

    eventSource.onmessage = (event) => {
      try {
        const data: JobProgress = JSON.parse(event.data)
        setJobProgress(data)

        // Update job status
        const statusMap: Record<string, JobStatus> = {
          pending: JobStatus.PENDING,
          started: JobStatus.STARTED,
          progress: JobStatus.PROGRESS,
          success: JobStatus.SUCCESS,
          failure: JobStatus.FAILURE,
        }

        setCurrentJob({
          id: data.id,
          status: statusMap[data.status] || JobStatus.PENDING,
          progress: data.progress,
          message: data.message,
          created_at: new Date().toISOString(),
          updated_at: new Date().toISOString(),
        })

        // Check if job is complete
        if (data.status === 'success' || data.status === 'failure') {
          setIsImporting(false)
          eventSource.close()
          eventSourceRef.current = null

          // Fetch final job result to get added/existing counts
          if (data.status === 'success') {
            fetchJobResult(jobId)
          }
        }
      } catch (err) {
        console.error('Error parsing SSE event:', err)
      }
    }

    eventSource.onerror = (err) => {
      console.error('SSE error:', err)
      eventSource.close()
      eventSourceRef.current = null
    }
  }

  const fetchJobResult = async (jobId: string) => {
    try {
      const job = await jobsApi.getJob(jobId)
      // Job result may contain added/existing counts in metadata
      // For now, we'll just update the job status
      setCurrentJob(job)
    } catch (err) {
      console.error('Error fetching job result:', err)
    }
  }

  const getStatusColor = (status: JobStatus) => {
    switch (status) {
      case JobStatus.SUCCESS:
        return 'text-green-600'
      case JobStatus.FAILURE:
        return 'text-red-600'
      case JobStatus.STARTED:
      case JobStatus.PROGRESS:
        return 'text-blue-600'
      default:
        return 'text-gray-600'
    }
  }

  return (
    <div className="p-6">

      <div className="space-y-6">
        {/* Folder Scan Section */}
        <div className="bg-white rounded-lg shadow p-6">
          <h2 className="text-lg font-semibold text-gray-900 mb-4">
            Scan Folder
          </h2>

          <div className="space-y-4">
            <div>
              <label
                htmlFor="folder-path"
                className="block text-sm font-medium text-gray-700 mb-2"
              >
                Folder Path
              </label>
              <div className="flex gap-2">
                <input
                  id="folder-path"
                  type="text"
                  value={folderPath}
                  onChange={(e) => setFolderPath(e.target.value)}
                  placeholder="/path/to/photos"
                  className="w-1/2 px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
                  disabled={isImporting}
                />
                <button
                  type="button"
                  onClick={handleFolderBrowse}
                  disabled={isImporting || isBrowsing}
                  className="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
                >
                  {isBrowsing ? 'Opening...' : 'Browse'}
                </button>
              </div>
              <p className="mt-1 text-sm text-gray-500">
                Enter the full absolute path to the folder containing photos / videos.
              </p>
            </div>

            <div className="flex items-center">
              <input
                id="recursive"
                type="checkbox"
                checked={recursive}
                onChange={(e) => setRecursive(e.target.checked)}
                disabled={isImporting}
                className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
              />
              <label
                htmlFor="recursive"
                className="ml-2 block text-sm text-gray-700"
              >
                Scan subdirectories recursively
              </label>
            </div>

            <button
              type="button"
              onClick={handleScanFolder}
              disabled={isImporting || !folderPath.trim()}
              className="px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
            >
              {isImporting ? 'Scanning...' : 'Start Scanning'}
            </button>
          </div>
        </div>

        {/* Progress Section */}
        {(currentJob || jobProgress) && (
          <div className="bg-white rounded-lg shadow p-6">
            <h2 className="text-lg font-semibold text-gray-900 mb-4">
              Import Progress
            </h2>

            {currentJob && (
              <div className="space-y-4">
                <div>
                  <div className="flex justify-between items-center mb-2">
                    <span
                      className={`text-sm font-medium ${getStatusColor(currentJob.status)}`}
                    >
                      {currentJob.status === JobStatus.SUCCESS && '✓ '}
                      {currentJob.status === JobStatus.FAILURE && '✗ '}
                      {currentJob.status.charAt(0).toUpperCase() +
                        currentJob.status.slice(1)}
                    </span>
                    <span className="text-sm text-gray-600">
                      {currentJob.progress}%
                    </span>
                  </div>
                  <div className="w-full bg-gray-200 rounded-full h-2">
                    <div
                      className="bg-blue-600 h-2 rounded-full transition-all duration-300"
                      style={{ width: `${currentJob.progress}%` }}
                    />
                  </div>
                </div>

                {jobProgress && (
                  <div className="text-sm text-gray-600">
                    {jobProgress.processed !== undefined &&
                      jobProgress.total !== undefined && (
                        <p>
                          Processed: {jobProgress.processed} /{' '}
                          {jobProgress.total}
                        </p>
                      )}
                    {jobProgress.message && (
                      <p className="mt-1">{jobProgress.message}</p>
                    )}
                  </div>
                )}
              </div>
            )}
          </div>
        )}

        {/* Results Section */}
        {importResult && (
          <div className="bg-white rounded-lg shadow p-6">
            <h2 className="text-lg font-semibold text-gray-900 mb-4">
              Import Results
            </h2>

            <div className="space-y-2 text-sm">
              {importResult.added !== undefined && (
                <p className="text-green-600">
                  ✓ {importResult.added} new photos added
                </p>
              )}
              {importResult.existing !== undefined && (
                <p className="text-gray-600">
                  {importResult.existing} photos already in database
                </p>
              )}
              {importResult.total !== undefined && (
                <p className="text-gray-700 font-medium">
                  Total: {importResult.total} photos
                </p>
              )}
            </div>
          </div>
        )}

        {/* Error Section */}
        {error && (
          <div className="bg-red-50 border border-red-200 rounded-lg p-4">
            <p className="text-sm text-red-800">{error}</p>
          </div>
        )}
      </div>
    </div>
  )
}
