"use client";

import { useEffect, useRef, useState } from "react";
import { useParams } from "next/navigation";

type Inspection = { proposal: string; vehicleType: "light" | "motorcycle" | "heavy"; plate: string; vehicle: string | null };
const scripts = {
  light: ["Dianteira", "Lateral do motorista", "Traseira", "Lateral do passageiro", "Placa", "Chassi", "Motor", "Painel ligado"],
  motorcycle: ["Lateral direita", "Lateral esquerda", "Traseira", "Placa", "Chassi", "Painel ligado"],
  heavy: ["Cabine e dianteira", "Laterais e traseira", "Placa", "Chassi e motor", "Pneus e eixos", "Implemento e painel"],
};

export default function MobileInspectionPage() {
  const { token } = useParams<{ token: string }>();
  const [inspection, setInspection] = useState<Inspection | null>(null);
  const [completed, setCompleted] = useState<string[]>([]);
  const [step, setStep] = useState(0);
  const [message, setMessage] = useState("Carregando sua vistoria...");
  const [busy, setBusy] = useState(false);
  const [retakeRequired, setRetakeRequired] = useState(false);
  const [cameraOpen, setCameraOpen] = useState(false);
  const [cameraStarting, setCameraStarting] = useState(false);
  const [location, setLocation] = useState<{ latitude: number; longitude: number } | null>(null);
  const [locationBusy, setLocationBusy] = useState(false);
  const [torchAvailable, setTorchAvailable] = useState(false);
  const [torchOn, setTorchOn] = useState(false);
  const [latestPreview, setLatestPreview] = useState<string | null>(null);
  const [capturedPreviews, setCapturedPreviews] = useState<{ category: string; url: string }[]>([]);
  const video = useRef<HTMLVideoElement>(null);
  const cameraStream = useRef<MediaStream | null>(null);

  const route = inspection ? scripts[inspection.vehicleType] : [];
  const category = route[step];

  useEffect(() => {
    fetch(`/api/vistoria/${token}`).then(async (response) => ({ response, body: await response.json() })).then(({ response, body }) => {
      if (!response.ok) throw new Error(body.error || "Não foi possível abrir a vistoria.");
      setInspection(body.inspection);
      const done = (body.photos as { category_code: string }[]).map((photo) => photo.category_code);
      setCompleted(done);
      const next = scripts[body.inspection.vehicleType as keyof typeof scripts].findIndex((item) => !done.includes(item));
      setStep(next === -1 ? 0 : next);
      setMessage(next === -1 ? "Todas as fotos necessárias já foram enviadas." : "Siga a orientação e tire a foto solicitada.");
    }).catch((error) => setMessage(error instanceof Error ? error.message : "Não foi possível abrir a vistoria."));
    return () => stopCamera();
  }, [token]);

  useEffect(() => {
    if (!cameraOpen || !video.current || !cameraStream.current) return;
    video.current.srcObject = cameraStream.current;
    video.current.play().catch(() => setMessage("A câmera foi autorizada, mas a prévia não iniciou. Toque em cancelar e abra a câmera novamente."));
  }, [cameraOpen]);

  async function openCamera() {
    if (!window.isSecureContext) {
      setMessage("A câmera só pode ser aberta por um link seguro (https). Abra novamente o link enviado pela vistoria.");
      return;
    }
    if (!navigator.mediaDevices?.getUserMedia) {
      setMessage("Este navegador não disponibiliza acesso à câmera. Abra o link no Chrome, Samsung Internet ou outro navegador atualizado.");
      return;
    }
    setCameraStarting(true);
    // Dispara o pedido ainda dentro do gesto do botão; alguns Androids ignoram
    // solicitações de geolocalização iniciadas depois de uma operação assíncrona.
    setLocationBusy(true);
    const locationPromise = requestLocation();
    try {
      setMessage("Solicitando acesso à câmera...");
      const stream = await getBackCameraStream();
      cameraStream.current = stream;
      const track = stream.getVideoTracks()[0];
      const capabilities = (track as unknown as { getCapabilities?: () => { torch?: boolean } })?.getCapabilities?.();
      setTorchAvailable(Boolean(capabilities?.torch));
      setTorchOn(false);
      setCameraOpen(true);
      void enterFullscreen();
      setMessage("Câmera aberta. Agora autorize a localização para liberar a captura.");
      void locationPromise.then((currentLocation) => {
        setLocation(currentLocation);
        setMessage("Localização confirmada. Centralize o veículo e capture a foto.");
      }).catch(() => {
        setLocation(null);
        setMessage("A localização é obrigatória. Toque em “Ativar localização” e permita o acesso quando o navegador solicitar.");
      }).finally(() => setLocationBusy(false));
    } catch (error) {
      void locationPromise.catch(() => undefined).finally(() => setLocationBusy(false));
      setMessage(cameraErrorMessage(error));
    } finally { setCameraStarting(false); }
  }

  async function updateLocation() {
    setLocationBusy(true);
    try {
      const currentLocation = await requestLocation();
      setLocation(currentLocation);
      setMessage("Localização confirmada. Centralize o veículo e capture a foto.");
    } catch {
      setLocation(null);
      setMessage("A localização é obrigatória. Toque em “Ativar localização” e permita o acesso quando o navegador solicitar.");
    } finally { setLocationBusy(false); }
  }

  async function toggleTorch() {
    const track = cameraStream.current?.getVideoTracks()[0];
    if (!track) return;
    try {
      await track.applyConstraints({ advanced: [{ torch: !torchOn }] } as unknown as MediaTrackConstraints);
      setTorchOn((current) => !current);
    } catch { setMessage("O flash não pôde ser ativado neste aparelho. Use iluminação externa e mantenha o veículo bem visível."); }
  }

  function stopCamera() {
    cameraStream.current?.getTracks().forEach((track) => track.stop());
    cameraStream.current = null;
    if (video.current) video.current.srcObject = null;
    setCameraOpen(false); setRetakeRequired(false); setTorchAvailable(false); setTorchOn(false);
    void exitFullscreen();
  }
  async function upload(image: Blob, filename: string, previewUrl: string) {
    if (!category || !location) {
      setMessage("A localização é obrigatória. Toque em Abrir câmera e permita o acesso à localização.");
      return;
    }
    if (!(await isLandscape(image))) {
      setMessage("A foto precisa ser horizontal. Gire o celular para a posição paisagem e tire novamente.");
      return;
    }
    setBusy(true); setMessage("A IA está analisando a qualidade, o enquadramento e a identificação da foto...");
    const body = new FormData(); body.append("category", category); body.append("image", image, filename); body.append("latitude", String(location.latitude)); body.append("longitude", String(location.longitude));
    try {
      const response = await fetch(`/api/vistoria/${token}`, { method: "POST", body });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || "Não foi possível enviar a foto.");
      if (!result.captureAccepted) {
        setRetakeRequired(true);
        setMessage(result.message || "Refaça esta foto antes de continuar. Revise o enquadramento e capture novamente.");
        return;
      }
      setRetakeRequired(false);
      setCapturedPreviews((current) => current.some((item) => item.category === category) ? current : [...current, { category, url: previewUrl }]);
      setCompleted((current) => [...new Set([...current, category])]);
      const next = route.findIndex((item, index) => index > step && !completed.includes(item));
      if (next >= 0) { setStep(next); setLatestPreview(null); setMessage(result.message || "Foto aprovada. Você pode seguir para a próxima orientação."); }
      else setMessage(result.message || "Foto recebida. Você concluiu este roteiro; a IA iniciará a análise das imagens.");
    } catch (error) { setMessage(error instanceof Error ? error.message : "Não foi possível enviar a foto."); }
    finally { setBusy(false); }
  }
  async function capture() {
    if (!video.current) return;
    if (!video.current.videoWidth || !video.current.videoHeight) {
      setMessage("A prévia da câmera ainda está iniciando. Aguarde um instante e tente capturar novamente.");
      return;
    }
    if (video.current.videoWidth < video.current.videoHeight) {
      setMessage("Mantenha o celular na horizontal antes de capturar a foto.");
      return;
    }
    const canvas = document.createElement("canvas"); canvas.width = video.current.videoWidth; canvas.height = video.current.videoHeight;
    canvas.getContext("2d")?.drawImage(video.current, 0, 0);
    canvas.toBlob((blob) => {
      if (!blob) { setMessage("Não foi possível preparar a foto. Tente capturar novamente."); return; }
      const previewUrl = URL.createObjectURL(blob);
      setLatestPreview(previewUrl);
      stopCamera();
      void upload(blob, `${category}.jpg`, previewUrl);
    }, "image/jpeg", 0.9);
  }

  if (!inspection) return <main className="capture-page"><div className="capture-phone"><p className="eyebrow">CAPITAL VISTORIAS</p><h1>{message}</h1></div></main>;
  const isComplete = completed.length >= route.length;
  const instruction = category === "Placa" ? `Fotografe a placa traseira de forma legível. A IA comparará com ${inspection.plate}; se for Mercosul, mantenha o QR Code visível.` : category === "Dianteira" || category === "Traseira" ? `Mostre o veículo inteiro e mantenha a placa visível. A IA conferirá a placa com ${inspection.plate}.` : category?.includes("Chassi") ? "Fotografe o identificador do chassi de perto, com todos os caracteres nítidos." : "Posicione o veículo em local iluminado e mantenha o enquadramento completo.";
  const technicalFailure = /análise automática ficou indisponível/i.test(message);
  return <main className="capture-page"><section className="capture-phone"><header><span className="logo-tiny">✓</span><b>Autovistoria Veicular</b><small>🔒 Link seguro</small></header>{isComplete ? <div className="capture-finished"><div className="finished-check">✓</div><p className="eyebrow">VISTORIA CONCLUÍDA</p><h1>Fotos enviadas com sucesso!</h1><p>Todas as fotos foram vinculadas à vistoria <b>{inspection.proposal}</b> e seguirão para análise automática.</p><div className="finished-vehicle"><span>{inspection.vehicle || "Veículo"}</span><b>{inspection.plate}</b></div><div className="finished-preview-list">{capturedPreviews.map((photo) => <figure key={photo.category}><img src={photo.url} alt={photo.category} /><figcaption>{photo.category}</figcaption></figure>)}</div><button className="finish-return" onClick={() => { if (window.history.length > 1) window.history.back(); else window.location.href = "https://www.google.com"; }}>Fechar vistoria</button><small>Você pode fechar esta página ou usar o botão acima para voltar.</small></div> : <div className="capture-content"><div className="capture-progress"><span>Foto {Math.min(step + 1, route.length)} de {route.length}</span><b>{Math.round((completed.length / route.length) * 100)}%</b></div><div className="capture-progress-bar"><i style={{ width: `${(completed.length / route.length) * 100}%` }} /></div><p className="eyebrow">{inspection.plate} · {inspection.proposal}</p><h1>{category}</h1><p className="capture-instruction">{instruction}</p><div className="capture-checklist"><b>Antes de fotografar</b><span>1. Gire o celular para a horizontal.</span><span>2. Mostre somente o ângulo solicitado.</span><span>3. Centralize o veículo e evite sombras.</span></div><div className="landscape-notice">↻ Para esta vistoria, o celular deve estar na horizontal.</div><div className="camera-stage">{latestPreview ? <img className="capture-preview" src={latestPreview} alt={`Prévia da foto ${category}`} /> : <VehicleGuide category={category || ""} vehicleType={inspection.vehicleType} />}<i className="frame tl" /><i className="frame tr" /><i className="frame bl" /><i className="frame br" /></div><div className="capture-tip"><b>{technicalFailure ? "Análise indisponível" : retakeRequired ? "Nova foto obrigatória" : "Localização obrigatória"}</b><p>{technicalFailure ? "A foto não foi avaliada pela IA. Não altere foco ou enquadramento sem orientação: tente novamente em alguns instantes." : retakeRequired ? "Veja a orientação da IA abaixo e refaça somente o que foi solicitado. Você só avança após uma foto aceita." : "A localização será solicitada ao abrir a câmera. Cada foto é vinculada à posição do aparelho."}</p>{!location && <button type="button" className="location-action" disabled={locationBusy} onClick={() => void updateLocation()}>{locationBusy ? "Solicitando localização..." : "Ativar localização"}</button>}</div>{busy ? <div className="ai-loading"><i /><div><b>IA analisando a foto</b><span>Não saia desta página. Aguarde a confirmação para continuar.</span></div></div> : <button className="capture-main" disabled={cameraStarting} onClick={openCamera}>{cameraStarting ? "Abrindo câmera..." : retakeRequired ? "↻ Refazer foto em tela cheia" : "Abrir câmera em tela cheia"}</button>}<div className={`capture-message ${retakeRequired || message.includes("Não foi possível") || message.includes("indisponível") || message.includes("localização") || message.includes("horizontal") ? "warning" : ""}`}>{message}</div></div>}</section>{cameraOpen && <section className="camera-fullscreen" aria-label="Câmera para captura"><video ref={video} autoPlay playsInline muted /><div className="camera-fullscreen-top"><button onClick={stopCamera}>× Cancelar</button><b>{category}</b>{torchAvailable ? <button className={torchOn ? "torch-on" : ""} onClick={() => void toggleTorch()}>⚡ {torchOn ? "Flash ligado" : "Flash"}</button> : <span>Flash indisponível</span>}</div><div className="camera-fullscreen-guide"><b>Gire o celular para a horizontal</b><span>Centralize o veículo dentro do quadro.</span></div><i className="frame tl" /><i className="frame tr" /><i className="frame bl" /><i className="frame br" /><div className="camera-fullscreen-bottom">{!location ? <button className="camera-location" disabled={locationBusy} onClick={() => void updateLocation()}>{locationBusy ? "Solicitando localização..." : "Ativar localização para capturar"}</button> : <button className="camera-shutter" onClick={capture} aria-label="Capturar foto"><i /></button>}<small>{location ? "Toque no botão para tirar a foto" : "A captura é liberada após a localização"}</small></div></section>}</main>;
}

async function getBackCameraStream() {
  const attempts: MediaStreamConstraints[] = [
    { video: { facingMode: { ideal: "environment" }, aspectRatio: { ideal: 4 / 3 }, width: { ideal: 1920 }, height: { ideal: 1080 } }, audio: false },
    { video: { facingMode: { ideal: "environment" } }, audio: false },
    { video: true, audio: false },
  ];
  let lastError: unknown;
  for (const constraints of attempts) {
    try { return await navigator.mediaDevices.getUserMedia(constraints); } catch (error) { lastError = error; }
  }
  throw lastError;
}

function cameraErrorMessage(error: unknown) {
  const name = error instanceof DOMException ? error.name : "";
  if (name === "NotAllowedError" || name === "SecurityError") return "A câmera foi bloqueada. No navegador, permita o uso da câmera para este site e toque em abrir câmera novamente.";
  if (name === "NotFoundError") return "Nenhuma câmera foi encontrada pelo navegador. Feche outros aplicativos que possam estar usando a câmera e tente novamente.";
  if (name === "NotReadableError") return "A câmera está sendo usada por outro aplicativo ou não pôde ser iniciada. Feche a câmera do celular e tente novamente.";
  if (name === "OverconstrainedError") return "Este aparelho não aceitou a configuração da câmera. Atualize a página e tente novamente.";
  return "Não foi possível abrir a câmera neste aparelho. Abra o link no Chrome ou Samsung Internet atualizado e confira a permissão da câmera.";
}

async function enterFullscreen() {
  try { await document.documentElement.requestFullscreen?.(); } catch { /* A sobreposição ocupa a tela mesmo quando o navegador bloqueia fullscreen. */ }
}

async function exitFullscreen() {
  try { if (document.fullscreenElement) await document.exitFullscreen(); } catch { /* sem ação necessária */ }
}

function VehicleGuide({ category, vehicleType }: { category: string; vehicleType: Inspection["vehicleType"] }) {
  const view = category.toLocaleLowerCase("pt-BR");
  const isMotorcycle = vehicleType === "motorcycle";
  const isPanel = view.includes("painel");
  const isEngine = view.includes("motor") || view.includes("chassi");
  const isFrontGuide = !isMotorcycle && !isPanel && !isEngine && (view.includes("dianteira") || view.includes("cabine"));
  const reference = isPanel ? "Centralize o painel ligado e os indicadores." : isEngine ? "Aproxime o identificador e mantenha todos os caracteres nítidos." : view.includes("placa") ? "Centralize a placa e mantenha os caracteres legíveis." : `Mostre todo o veículo pela ${category.toLocaleLowerCase("pt-BR")}.`;
  return <div className="vehicle-guide">{isFrontGuide ? <img className="guide-car-image" src="/images/vehicle-front-guide.png" alt="Silhueta de referência da dianteira do veículo" /> : <svg viewBox="0 0 320 190" role="img" aria-label={`Referência visual: ${category}`}>{isPanel ? <><rect x="43" y="30" width="234" height="128" rx="16" fill="#173d4b" stroke="#c9f4fb" strokeWidth="3"/><path d="M68 132h184" stroke="#7fdceb" strokeWidth="8" strokeLinecap="round"/><circle cx="112" cy="91" r="32" fill="#0e2a36" stroke="#8eeaf8" strokeWidth="4"/><circle cx="208" cy="91" r="32" fill="#0e2a36" stroke="#8eeaf8" strokeWidth="4"/><path d="M112 91l15-20M208 91l-13-19" stroke="#18c4e4" strokeWidth="4" strokeLinecap="round"/><rect x="137" y="67" width="46" height="47" rx="7" fill="#79ddec" fillOpacity=".3" stroke="#b9f7ff" strokeWidth="2"/></> : isMotorcycle ? <><path d="M72 136h175l-23-45h-62l-27 45Z" fill="#234d5c" stroke="#d3f6fb" strokeWidth="3"/><path d="M151 91 174 58h39l24 41" fill="none" stroke="#d3f6fb" strokeWidth="7" strokeLinecap="round" strokeLinejoin="round"/><circle cx="96" cy="137" r="28" fill="#0d2734" stroke="#8de1ed" strokeWidth="7"/><circle cx="225" cy="137" r="28" fill="#0d2734" stroke="#8de1ed" strokeWidth="7"/><path d="M112 120h97" stroke="#17c1e0" strokeWidth="8" strokeLinecap="round"/><path d="M173 58 144 54" stroke="#d3f6fb" strokeWidth="6" strokeLinecap="round"/><rect x="154" y="77" width="56" height="21" rx="7" fill="#c9f7ff" fillOpacity=".28"/></> : <><path d="M57 139c4-42 20-79 48-95 20-11 90-11 110 0 28 16 44 53 48 95l-18 17H75Z" fill="#244f5f" stroke="#d9f7fb" strokeWidth="3"/><path d="M104 54c13-12 99-12 112 0l17 46H87Z" fill="#bcecf4" fillOpacity=".38" stroke="#d8f9fc" strokeWidth="3"/><path d="M96 111h128" stroke="#5d9daa" strokeWidth="5"/><path d="M75 142h170" stroke="#dffaff" strokeWidth="3"/><rect x="126" y="119" width="68" height="18" rx="5" fill="#0d2f3d" stroke="#8deafa" strokeWidth="2"/><path d="M88 128h24M208 128h24" stroke="#23c3e1" strokeWidth="10" strokeLinecap="round"/><circle cx="100" cy="151" r="18" fill="#102b38" stroke="#8cddeb" strokeWidth="5"/><circle cx="220" cy="151" r="18" fill="#102b38" stroke="#8cddeb" strokeWidth="5"/>{isEngine && <rect x="118" y="89" width="84" height="37" rx="8" fill="#19c8e5" fillOpacity=".28" stroke="#8ff0ff" strokeWidth="3"/>}</>}</svg>}<div><b>Referência da foto</b><small>{reference}</small></div></div>;
}

function requestLocation() {
  return new Promise<{ latitude: number; longitude: number }>((resolve, reject) => {
    if (!navigator.geolocation) return reject(new Error("Este aparelho não disponibiliza geolocalização."));
    navigator.geolocation.getCurrentPosition(
      (position) => resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude }),
      () => reject(new Error("A localização é obrigatória. Autorize o acesso à localização nas permissões do navegador e tente novamente.")),
      { enableHighAccuracy: true, timeout: 15_000, maximumAge: 30_000 },
    );
  });
}

async function isLandscape(image: Blob) {
  if ("createImageBitmap" in window) {
    const bitmap = await createImageBitmap(image);
    const landscape = bitmap.width >= bitmap.height;
    bitmap.close();
    return landscape;
  }
  return new Promise<boolean>((resolve) => {
    const preview = new Image(); const url = URL.createObjectURL(image);
    preview.onload = () => { URL.revokeObjectURL(url); resolve(preview.naturalWidth >= preview.naturalHeight); };
    preview.onerror = () => { URL.revokeObjectURL(url); resolve(false); };
    preview.src = url;
  });
}
