import { useCallback, useEffect, useRef, useState } from "react"
import MetricCard from "../components/MetricCard"
import StatusBadge from "../components/StatusBadge"
import { inspectFrame, inspectImage } from "../lib/api"
import { formatDateTime, titleCase } from "../lib/formatters"
import { getDecisionTone } from "../lib/status"

function fileToDataUrl(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => resolve(reader.result)
    reader.onerror = () => reject(new Error("Unable to read the selected image"))
    reader.readAsDataURL(file)
  })
}

function playAlertTone() {
  const AudioContextRef = window.AudioContext || window.webkitAudioContext
  if (!AudioContextRef) return

  const audioContext = new AudioContextRef()
  const oscillator = audioContext.createOscillator()
  const gainNode = audioContext.createGain()

  oscillator.type = "triangle"
  oscillator.frequency.setValueAtTime(880, audioContext.currentTime)
  gainNode.gain.setValueAtTime(0.0001, audioContext.currentTime)
  gainNode.gain.exponentialRampToValueAtTime(0.08, audioContext.currentTime + 0.02)
  gainNode.gain.exponentialRampToValueAtTime(0.0001, audioContext.currentTime + 0.28)

  oscillator.connect(gainNode)
  gainNode.connect(audioContext.destination)
  oscillator.start()
  oscillator.stop(audioContext.currentTime + 0.3)
}

export default function Live() {
  const [mode, setMode] = useState("upload")
  const [selectedFile, setSelectedFile] = useState(null)
  const [imagePreview, setImagePreview] = useState("")
  const [inspectionResult, setInspectionResult] = useState(null)
  const [isInspecting, setIsInspecting] = useState(false)
  const [error, setError] = useState("")
  const [cameraReady, setCameraReady] = useState(false)
  const [streaming, setStreaming] = useState(false)
  const [autoInspect, setAutoInspect] = useState(true)
  const [persistLive, setPersistLive] = useState(false)
  const [deepAnalysisEnabled, setDeepAnalysisEnabled] = useState(false)
  const [alertsEnabled, setAlertsEnabled] = useState(true)
  const [cameraStatus, setCameraStatus] = useState("Camera offline")
  const [lastInspectedAt, setLastInspectedAt] = useState("")

  const videoRef = useRef(null)
  const canvasRef = useRef(null)
  const streamRef = useRef(null)
  const requestInFlight = useRef(false)
  const lastAlertDecision = useRef("")

  async function handleImageSelection(event) {
    const file = event.target.files?.[0]

    if (!file) return

    setError("")
    setSelectedFile(file)

    try {
      const previewUrl = await fileToDataUrl(file)
      setImagePreview(previewUrl)
    } catch (selectionError) {
      setError(selectionError.message)
    }
  }

  async function handleImageInspection() {
    if (!selectedFile) {
      setError("Select an image to run inspection.")
      return
    }

    setIsInspecting(true)
    setError("")

    try {
      const imageBase64 = await fileToDataUrl(selectedFile)
      const result = await inspectImage({
        image_base64: imageBase64,
        filename: selectedFile.name,
        source: "upload",
        persist: true,
        llm_mode: deepAnalysisEnabled ? "always" : "off",
      })

      setInspectionResult(result)
      setLastInspectedAt(result.timestamp)
      if (alertsEnabled && result.decision === "FAIL" && lastAlertDecision.current !== "FAIL") {
        playAlertTone()
      }
      lastAlertDecision.current = result.decision
    } catch (inspectionError) {
      setError(inspectionError.message)
    } finally {
      setIsInspecting(false)
    }
  }

  async function startCamera() {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: {
          facingMode: "environment",
          width: { ideal: 1280 },
          height: { ideal: 720 },
        },
        audio: false,
      })

      streamRef.current = stream

      if (videoRef.current) {
        videoRef.current.srcObject = stream
        await videoRef.current.play()
      }

      setCameraReady(true)
      setStreaming(true)
      setCameraStatus("Camera active and scanning live frames")
      setError("")
    } catch {
      setError("Camera access was blocked or unavailable.")
    }
  }

  function stopCamera() {
    if (streamRef.current) {
      streamRef.current.getTracks().forEach((track) => track.stop())
      streamRef.current = null
    }

    if (videoRef.current) {
      videoRef.current.srcObject = null
    }

    requestInFlight.current = false
    setStreaming(false)
    setCameraReady(false)
    setCameraStatus("Camera offline")
  }

  const captureAndInspectFrame = useCallback(async ({ persist = false } = {}) => {
    if (!videoRef.current || !canvasRef.current || requestInFlight.current) return
    if (videoRef.current.readyState < 2) return

    const canvas = canvasRef.current
    const videoWidth = videoRef.current.videoWidth || 1280
    const videoHeight = videoRef.current.videoHeight || 720
    const targetWidth = Math.min(768, videoWidth)
    const targetHeight = Math.round((videoHeight / videoWidth) * targetWidth)

    canvas.width = targetWidth
    canvas.height = targetHeight

    const context = canvas.getContext("2d")
    if (!context) {
      setError("Unable to capture the current camera frame.")
      return
    }

    context.drawImage(videoRef.current, 0, 0, targetWidth, targetHeight)

    requestInFlight.current = true
    setIsInspecting(true)
    setCameraStatus("Inspecting live frame")
    setError("")

    try {
      const result = await inspectFrame({
        image_base64: canvas.toDataURL("image/jpeg", 0.82),
        source: "camera",
        persist,
        llm_mode: deepAnalysisEnabled ? "always" : "off",
      })

      setInspectionResult(result)
      setLastInspectedAt(result.timestamp)
      setCameraStatus(
        result.total_defects > 0
          ? `Detected ${result.total_defects} defect${result.total_defects > 1 ? "s" : ""} in the latest frame`
          : "No actionable defects detected in the latest frame"
      )

      if (alertsEnabled && result.decision === "FAIL" && lastAlertDecision.current !== "FAIL") {
        playAlertTone()
      }
      lastAlertDecision.current = result.decision
    } catch (inspectionError) {
      setError(inspectionError.message)
      setCameraStatus("Camera active, waiting for a successful inspection response")
    } finally {
      requestInFlight.current = false
      setIsInspecting(false)
    }
  }, [alertsEnabled, deepAnalysisEnabled])

  useEffect(() => {
    return () => {
      stopCamera()
    }
  }, [])

  useEffect(() => {
    if (mode !== "camera" || !streaming || !cameraReady || !autoInspect) return undefined

    const interval = window.setInterval(() => {
      captureAndInspectFrame({ persist: persistLive })
    }, 2000)

    return () => {
      window.clearInterval(interval)
    }
  }, [autoInspect, cameraReady, captureAndInspectFrame, mode, persistLive, streaming])

  useEffect(() => {
    if (!cameraReady || mode !== "camera") return

    const timer = window.setTimeout(() => {
      captureAndInspectFrame({ persist: persistLive })
    }, 500)

    return () => {
      window.clearTimeout(timer)
    }
  }, [cameraReady, captureAndInspectFrame, mode, persistLive])

  useEffect(() => {
    if (mode === "camera") {
      setSelectedFile(null)
      setImagePreview("")
      return
    }

    setStreaming(false)
    setCameraStatus("Camera offline")
  }, [mode])

  return (
    <div className="space-y-6 pb-10">
      <section className="surface-card p-6 md:p-8">
        <div className="grid gap-6 xl:grid-cols-[1.25fr_0.75fr]">
          <div>
            <p className="eyebrow">Live Monitoring Page</p>
            <h2 className="hero-title mt-3">Upload images or use the browser camera for organized, real-time manufacturing inspection.</h2>
            <p className="body-copy mt-5 max-w-3xl">
              Use the live workspace to inspect saved images, scan frames from the browser camera, and review defect decisions with optional AI recommendations.
            </p>

            <div className="mt-6 flex flex-wrap gap-3">
              <button
                type="button"
                className={mode === "upload" ? "primary-btn" : "secondary-btn"}
                onClick={() => setMode("upload")}
              >
                Upload images
              </button>
              <button
                type="button"
                className={mode === "camera" ? "primary-btn" : "secondary-btn"}
                onClick={() => setMode("camera")}
              >
                Live camera feed
              </button>
            </div>
          </div>

          <div className="surface-card p-6">
            <p className="eyebrow">Camera Setup</p>
            <p className="mt-4 text-sm leading-7 text-slate-300">
              For reliable live detection, keep the steel surface clearly visible in a stable top view. Reduce background clutter, avoid steep camera angles, and keep lighting even across the surface.
            </p>
          </div>
        </div>
      </section>

      <section className="grid gap-6 xl:grid-cols-[1.05fr_0.95fr]">
        <div className="surface-card p-6">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <p className="eyebrow">Detection Workspace</p>
              <h3 className="section-title mt-2">
                {mode === "upload" ? "Image-based inspection" : "Camera-based live detection"}
              </h3>
            </div>
            {inspectionResult ? (
              <StatusBadge label={inspectionResult.decision} tone={getDecisionTone(inspectionResult.decision)} pulse={inspectionResult.decision === "FAIL"} />
            ) : null}
          </div>

          {mode === "upload" ? (
            <div className="mt-6 space-y-5">
              <label className="flex min-h-[240px] cursor-pointer flex-col items-center justify-center rounded-[28px] border border-dashed border-white/15 bg-white/5 px-6 py-8 text-center transition hover:border-cyan-300/40 hover:bg-cyan-400/[0.08]">
                <input type="file" accept="image/*" className="hidden" onChange={handleImageSelection} />
                <p className="text-lg font-medium text-slate-100">Drop or choose a steel surface image</p>
                <p className="mt-3 max-w-xl text-sm leading-7 text-slate-400">
                  Use this mode to inspect saved surface samples, log a full report, and broadcast the result to the dashboard and history views.
                </p>
              </label>

              {imagePreview ? (
                <div className="overflow-hidden rounded-[28px] border border-white/10 bg-slate-950/60">
                  <img src={imagePreview} alt="Selected inspection" className="max-h-[420px] w-full object-cover" />
                </div>
              ) : null}

              <div className="flex flex-wrap gap-3">
                <button type="button" className="primary-btn" onClick={handleImageInspection} disabled={isInspecting}>
                  {isInspecting ? "Inspecting image..." : "Run image inspection"}
                </button>
                <div className="rounded-full border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                  Uploaded inspections are saved as reports automatically.
                </div>
              </div>

              <label className="flex items-center justify-between rounded-3xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                <span>Enable GenAI deep analysis (slower response)</span>
                <input
                  type="checkbox"
                  checked={deepAnalysisEnabled}
                  onChange={(event) => setDeepAnalysisEnabled(event.target.checked)}
                  className="h-5 w-5 accent-cyan-300"
                />
              </label>

              <div className="rounded-3xl border border-amber-300/20 bg-amber-400/10 px-4 py-4 text-sm leading-7 text-amber-50">
                Fast mode is optimized for real-time monitoring. Turn on deep analysis only when you want the slower cloud GenAI recommendation layer.
              </div>
            </div>
          ) : (
            <div className="mt-6 space-y-5">
              <div className="grid gap-4 lg:grid-cols-2">
                <div className="overflow-hidden rounded-[28px] border border-white/10 bg-slate-950/60">
                  <video ref={videoRef} className="aspect-video w-full object-cover" muted playsInline />
                </div>

                <div className="rounded-[28px] border border-white/10 bg-white/5 p-5">
                  <p className="eyebrow">Camera Controls</p>
                  <div className="mt-4 flex flex-wrap gap-3">
                    {!cameraReady ? (
                      <button type="button" className="primary-btn" onClick={startCamera}>
                        Enable camera
                      </button>
                    ) : (
                      <>
                        <button
                          type="button"
                          className={streaming ? "secondary-btn" : "primary-btn"}
                          onClick={() => setStreaming((current) => !current)}
                        >
                          {streaming ? "Pause live inspection" : "Start live inspection"}
                        </button>
                        <button
                          type="button"
                          className="secondary-btn"
                          onClick={() => captureAndInspectFrame({ persist: persistLive })}
                        >
                          Inspect current frame
                        </button>
                        <button type="button" className="secondary-btn" onClick={stopCamera}>
                          Stop camera
                        </button>
                      </>
                    )}
                  </div>

                  <div className="mt-5 space-y-3">
                    <label className="flex items-center justify-between rounded-3xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                      <span>Auto inspect every few seconds</span>
                      <input
                        type="checkbox"
                        checked={autoInspect}
                        onChange={(event) => setAutoInspect(event.target.checked)}
                        className="h-5 w-5 accent-cyan-300"
                      />
                    </label>
                    <label className="flex items-center justify-between rounded-3xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                      <span>Log live detections to reports and database</span>
                      <input
                        type="checkbox"
                        checked={persistLive}
                        onChange={(event) => setPersistLive(event.target.checked)}
                        className="h-5 w-5 accent-cyan-300"
                      />
                    </label>
                    <label className="flex items-center justify-between rounded-3xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                      <span>Enable GenAI deep analysis (slower response)</span>
                      <input
                        type="checkbox"
                        checked={deepAnalysisEnabled}
                        onChange={(event) => setDeepAnalysisEnabled(event.target.checked)}
                        className="h-5 w-5 accent-cyan-300"
                      />
                    </label>
                    <label className="flex items-center justify-between rounded-3xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-slate-300">
                      <span>Play alert tone on FAIL states</span>
                      <input
                        type="checkbox"
                        checked={alertsEnabled}
                        onChange={(event) => setAlertsEnabled(event.target.checked)}
                        className="h-5 w-5 accent-cyan-300"
                      />
                    </label>
                  </div>

                  <div className="mt-5 rounded-3xl border border-cyan-300/20 bg-cyan-400/10 px-4 py-4 text-sm text-cyan-50">
                    <p className="font-medium uppercase tracking-[0.2em] text-cyan-100/80">Live Status</p>
                    <p className="mt-2 leading-7">{cameraStatus}</p>
                    <p className="mt-2 text-cyan-100/80">
                      {lastInspectedAt ? `Last inspection: ${formatDateTime(lastInspectedAt)}` : "Waiting for the first live inspection result."}
                    </p>
                  </div>
                  <div className="rounded-3xl border border-white/10 bg-white/5 px-4 py-4 text-sm leading-7 text-slate-300">
                    Calibrate the camera so the top view of the steel surface fills most of the frame. This gives the detector a cleaner visual field and improves live inspection consistency.
                  </div>
                  <div className="rounded-3xl border border-amber-300/20 bg-amber-400/10 px-4 py-4 text-sm leading-7 text-amber-50">
                    Keep deep analysis off during continuous monitoring for the fastest response. Turn it on only when you want a slower GenAI disposition note for a specific frame.
                  </div>
                </div>
              </div>

              <canvas ref={canvasRef} className="hidden" />
            </div>
          )}

          {error ? (
            <div className="mt-5 rounded-3xl border border-rose-300/30 bg-rose-400/10 px-4 py-4 text-sm text-rose-100">
              {error}
            </div>
          ) : null}
        </div>

        <div className="space-y-6">
          <div className="surface-card p-6">
            <p className="eyebrow">Inspection Result</p>
            <h3 className="section-title mt-2">Annotated output and operator guidance</h3>

            {inspectionResult?.annotated_image ? (
              <div className="mt-5 overflow-hidden rounded-[28px] border border-white/10 bg-slate-950/60">
                <img
                  src={inspectionResult.annotated_image}
                  alt="Annotated inspection result"
                  className="max-h-[420px] w-full object-cover"
                />
              </div>
            ) : (
              <div className="mt-5 rounded-[28px] border border-dashed border-white/15 bg-white/5 p-6 text-sm leading-7 text-slate-400">
                Run an inspection to see the AI overlay, severity callouts, and decision banner.
              </div>
            )}

            {inspectionResult ? (
              <div className="mt-5 space-y-4">
                <div className="flex flex-wrap items-center gap-3">
                  <StatusBadge label={inspectionResult.decision} tone={getDecisionTone(inspectionResult.decision)} pulse={inspectionResult.decision === "FAIL"} />
                  <div className="rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm text-slate-300">
                    {formatDateTime(inspectionResult.timestamp)}
                  </div>
                </div>

                <p className="text-sm leading-7 text-slate-300">{inspectionResult.recommendation}</p>

                <div className="rounded-[28px] border border-cyan-300/20 bg-cyan-400/10 p-5">
                  <div className="flex flex-wrap items-center gap-3">
                    <StatusBadge
                      label={
                        inspectionResult.agent_mode === "llm"
                          ? "Decision Copilot"
                          : "Rules Engine"
                      }
                      tone={
                        inspectionResult.agent_mode === "llm"
                          ? "info"
                          : "warning"
                      }
                    />
                    <div className="rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm text-slate-200">
                      {inspectionResult.agent_provider} {inspectionResult.agent_model && inspectionResult.agent_model !== "fallback" ? `· ${inspectionResult.agent_model}` : ""}
                    </div>
                  </div>
                  <p className="mt-4 text-sm leading-7 text-cyan-50/95">
                    {inspectionResult.summary_text || "Decision support guidance is not available for this inspection yet."}
                  </p>
                </div>

                <div className="grid gap-4 sm:grid-cols-3">
                  <MetricCard label="Minor" value={inspectionResult.minor} detail="Low severity anomalies" tone="success" />
                  <MetricCard label="Moderate" value={inspectionResult.moderate} detail="Review threshold" tone="warning" />
                  <MetricCard label="Critical" value={inspectionResult.critical} detail="Immediate action" tone="danger" />
                </div>

                <div className="space-y-3">
                  {(inspectionResult.defects || []).length ? (
                    (inspectionResult.defects || []).map((defect, index) => (
                      <div key={`${defect.type}-${index}`} className="rounded-3xl border border-white/10 bg-white/5 px-4 py-4">
                        <div className="flex flex-wrap items-center justify-between gap-3">
                          <p className="text-base font-medium text-slate-50">{titleCase(defect.type)}</p>
                          <StatusBadge label={defect.severity} tone={getDecisionTone(defect.decision)} />
                        </div>
                        <p className="mt-3 text-sm leading-7 text-slate-300">
                          Confidence {defect.confidence ?? "--"} | Area ratio {defect.area_ratio} | Length {defect.length}
                        </p>
                      </div>
                    ))
                  ) : (
                    <div className="rounded-3xl border border-emerald-300/20 bg-emerald-400/10 px-4 py-4 text-sm leading-7 text-emerald-50">
                      The latest frame is clear. The system still inspected the image and returned a PASS result with no actionable defects detected.
                    </div>
                  )}
                </div>
              </div>
            ) : null}
          </div>

          <div className="surface-card p-6">
            <p className="eyebrow">Live Monitoring Notes</p>
            <h3 className="section-title mt-2">What improves real-time stability</h3>
            <div className="mt-5 grid gap-4 text-sm leading-7 text-slate-300">
              <div className="rounded-3xl border border-white/10 bg-white/5 p-4">
                Mount or position the camera so the steel surface is visible in a stable top view.
              </div>
              <div className="rounded-3xl border border-white/10 bg-white/5 p-4">
                Keep the surface centered and avoid hands, faces, tools, or other objects crossing into the frame.
              </div>
              <div className="rounded-3xl border border-white/10 bg-white/5 p-4">
                Use deep AI analysis for manual review, not for every live frame, when you want the fastest monitoring loop.
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
  )
}
