import { useState, useRef, useEffect } from 'react'
import { facesApi, ProcessFacesRequest } from '../api/faces'
import { jobsApi, JobResponse, JobStatus } from '../api/jobs'
import { useDeveloperMode } from '../context/DeveloperModeContext'

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

const DETECTOR_OPTIONS = ['retinaface', 'mtcnn', 'opencv', 'ssd']
const MODEL_OPTIONS = ['ArcFace', 'Facenet', 'Facenet512', 'VGG-Face']

export default function Process() {
  const { isDeveloperMode } = useDeveloperMode()
  const [batchSize, setBatchSize] = useState<number | undefined>(undefined)
  const [detectorBackend, setDetectorBackend] = useState('retinaface')
  const [modelName, setModelName] = useState('ArcFace')
  const [isProcessing, setIsProcessing] = useState(false)
  const [currentJob, setCurrentJob] = useState<JobResponse | null>(null)
  const [jobProgress, setJobProgress] = useState<JobProgress | 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 handleStartProcessing = async () => {
    setIsProcessing(true)
    setError(null)
    setCurrentJob(null)
    setJobProgress(null)

    try {
      const request: ProcessFacesRequest = {
        batch_size: batchSize || undefined,
        detector_backend: detectorBackend,
        model_name: modelName,
      }

      const response = await facesApi.processFaces(request)
      
      // Set processing state immediately
      setIsProcessing(true)
      
      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 || 'Processing failed')
      setIsProcessing(false)
    }
  }

  const handleStopProcessing = async () => {
    // Use jobProgress if currentJob is not available (might happen if status is still Pending)
    const jobId = currentJob?.id || jobProgress?.id
    
    if (!jobId) {
      console.error('Cannot stop: No job ID available')
      setError('Cannot stop: No active job found')
      return
    }

    console.log(`[Process] STOP button clicked for job ${jobId}`)
    
    try {
      // Call API to cancel the job
      console.log(`[Process] Calling cancelJob API for job ${jobId}`)
      const result = await jobsApi.cancelJob(jobId)
      console.log('[Process] Job cancellation requested:', result)
      
      // Update job status to show cancellation is in progress
      if (currentJob) {
        setCurrentJob({
          ...currentJob,
          status: JobStatus.PROGRESS,
          message: 'Cancellation requested - finishing current photo...',
        })
      } else if (jobProgress) {
        // If currentJob is not set, update jobProgress
        setJobProgress({
          ...jobProgress,
          status: 'progress',
          message: 'Cancellation requested - finishing current photo...',
        })
      }
      
      // Don't close SSE stream yet - keep it open to wait for job to actually stop
      // The job will finish the current photo, then stop and send a final status update
      // The SSE stream handler will close the stream when job status becomes SUCCESS or FAILURE
      
      // Set a flag to indicate cancellation was requested
      // This will be checked in the SSE handler
      setError(null) // Clear any previous errors
    } catch (err: any) {
      console.error('[Process] Error cancelling job:', err)
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to cancel job'
      setError(errorMessage)
      console.error('[Process] Full error details:', {
        message: err.message,
        response: err.response?.data,
        status: err.response?.status,
      })
    }
  }

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

    const eventSource = jobsApi.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,
          cancelled: JobStatus.CANCELLED,
        }

        const jobStatus = statusMap[data.status] || JobStatus.PENDING

        setCurrentJob({
          id: data.id,
          status: jobStatus,
          progress: data.progress,
          message: data.message,
          created_at: new Date().toISOString(),
          updated_at: new Date().toISOString(),
        })

        // Keep processing state true while job is running
        if (jobStatus === JobStatus.STARTED || jobStatus === JobStatus.PROGRESS) {
          setIsProcessing(true)
        }

        // Check if job is complete
        if (jobStatus === JobStatus.SUCCESS || jobStatus === JobStatus.FAILURE || jobStatus === JobStatus.CANCELLED) {
          setIsProcessing(false)
          eventSource.close()
          eventSourceRef.current = null

          // Handle cancelled jobs
          if (jobStatus === JobStatus.CANCELLED) {
            const progressInfo = data.processed !== undefined && data.total !== undefined
              ? ` (processed ${data.processed} of ${data.total} photos)`
              : ''
            setError(`Processing stopped: ${data.message || 'Cancelled by user'}${progressInfo}`)
          }
          // Show error message for failures
          else if (jobStatus === JobStatus.FAILURE) {
            // Show failure message with progress info if available
            const progressInfo = data.processed !== undefined && data.total !== undefined
              ? ` (processed ${data.processed} of ${data.total} photos)`
              : ''
            setError(`Processing failed: ${data.message || 'Unknown error'}${progressInfo}`)
          }

          // Fetch final job result to get processing stats for successful or cancelled jobs
          if (jobStatus === JobStatus.SUCCESS || jobStatus === JobStatus.CANCELLED) {
            fetchJobResult(jobId)
          }
        }
      } catch (err) {
        console.error('Error parsing SSE event:', err)
      }
    }

    eventSource.onerror = (err) => {
      console.error('SSE error:', err)
      // Don't automatically set isProcessing to false on error
      // Job might still be running even if SSE connection failed
      // Check job status directly instead
      if (currentJob) {
        // Try to fetch job status directly
        jobsApi.getJob(currentJob.id).then((job) => {
          const stillRunning = job.status === JobStatus.STARTED || job.status === JobStatus.PROGRESS
          setIsProcessing(stillRunning)
          setCurrentJob(job)
        }).catch(() => {
          // If we can't get status, assume job might still be running
          console.warn('Could not fetch job status after SSE error')
        })
      }
    }
  }

  const fetchJobResult = async (jobId: string) => {
    try {
      const job = await jobsApi.getJob(jobId)
      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">
        {/* Configuration Section */}
        <div className="bg-white rounded-lg shadow p-6">
          <h2 className="text-lg font-semibold text-gray-900 mb-4">
            Processing Configuration
          </h2>

          <div className="space-y-4">
            {/* Batch Size */}
            <div>
              <label
                htmlFor="batch-size"
                className="block text-sm font-medium text-gray-700 mb-1"
              >
                Batch Size
              </label>
              <input
                id="batch-size"
                type="text"
                inputMode="numeric"
                pattern="[0-9]*"
                value={batchSize || ''}
                onChange={(e) => {
                  const value = e.target.value
                  // Only allow numeric input
                  if (value === '' || /^\d+$/.test(value)) {
                    setBatchSize(value ? parseInt(value, 10) : undefined)
                  }
                }}
                onKeyDown={(e) => {
                  // Allow: backspace, delete, tab, escape, enter, and decimal point
                  if (
                    [8, 9, 27, 13, 46, 110, 190].indexOf(e.keyCode) !== -1 ||
                    // Allow: Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X
                    (e.keyCode === 65 && e.ctrlKey === true) ||
                    (e.keyCode === 67 && e.ctrlKey === true) ||
                    (e.keyCode === 86 && e.ctrlKey === true) ||
                    (e.keyCode === 88 && e.ctrlKey === true) ||
                    // Allow: home, end, left, right
                    (e.keyCode >= 35 && e.keyCode <= 39)
                  ) {
                    return
                  }
                  // Ensure that it is a number and stop the keypress
                  if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
                    e.preventDefault()
                  }
                }}
                className="w-32 px-2 py-1 text-sm border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
                disabled={isProcessing}
              />
              <p className="mt-1 text-xs text-gray-500">
                Leave empty to process all unprocessed photos
              </p>
            </div>

            {/* Detector Backend - Only visible in developer mode */}
            {isDeveloperMode && (
              <div>
                <label
                  htmlFor="detector-backend"
                  className="block text-sm font-medium text-gray-700 mb-2"
                >
                  Face Detector
                </label>
                <select
                  id="detector-backend"
                  value={detectorBackend}
                  onChange={(e) => setDetectorBackend(e.target.value)}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
                  disabled={isProcessing}
                >
                  {DETECTOR_OPTIONS.map((option) => (
                    <option key={option} value={option}>
                      {option.charAt(0).toUpperCase() + option.slice(1)}
                    </option>
                  ))}
                </select>
                <p className="mt-1 text-sm text-gray-500">
                  RetinaFace recommended for best accuracy
                </p>
              </div>
            )}

            {/* Model Name - Only visible in developer mode */}
            {isDeveloperMode && (
              <div>
                <label
                  htmlFor="model-name"
                  className="block text-sm font-medium text-gray-700 mb-2"
                >
                  Recognition Model
                </label>
                <select
                  id="model-name"
                  value={modelName}
                  onChange={(e) => setModelName(e.target.value)}
                  className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
                  disabled={isProcessing}
                >
                  {MODEL_OPTIONS.map((option) => (
                    <option key={option} value={option}>
                      {option}
                    </option>
                  ))}
                </select>
                <p className="mt-1 text-gray-500">
                  ArcFace recommended for best accuracy
                </p>
              </div>
            )}

            {/* Control Buttons */}
            <div className="flex gap-2 pt-4">
              <button
                type="button"
                onClick={handleStartProcessing}
                disabled={isProcessing}
                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"
              >
                {isProcessing ? 'Processing...' : 'Start Processing'}
              </button>
              {isProcessing && (
                <button
                  type="button"
                  onClick={(e) => {
                    e.preventDefault()
                    e.stopPropagation()
                    console.log('[Process] STOP button clicked, isProcessing:', isProcessing)
                    console.log('[Process] currentJob:', currentJob)
                    console.log('[Process] jobProgress:', jobProgress)
                    handleStopProcessing()
                  }}
                  className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 disabled:opacity-50 disabled:cursor-not-allowed"
                  disabled={!currentJob && !jobProgress}
                >
                  Stop
                </button>
              )}
            </div>
          </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">
              Processing 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 === JobStatus.CANCELLED && '⏹ '}
                      {currentJob.status === JobStatus.CANCELLED 
                        ? 'Stopped'
                        : 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="space-y-2 text-sm text-gray-600">
                    {jobProgress.processed !== undefined &&
                      jobProgress.total !== undefined && (
                        <p>
                          Photos processed: {jobProgress.processed} /{' '}
                          {jobProgress.total}
                        </p>
                      )}
                    {jobProgress.faces_detected !== undefined && (
                      <p>Faces detected: {jobProgress.faces_detected}</p>
                    )}
                    {jobProgress.faces_stored !== undefined && (
                      <p>Faces stored: {jobProgress.faces_stored}</p>
                    )}
                    {jobProgress.message && (
                      <p className="mt-1 font-medium">{jobProgress.message}</p>
                    )}
                  </div>
                )}
              </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>
  )
}
