"use client";
import { useRef, useState } from "react";
import { Upload, Loader2, CheckCircle2, Pause } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

type Session = { id: string; received: number; chunkSize: number; size: number; complete?: boolean };
async function result(response: Response) {
  if (response.redirected || !response.headers.get("content-type")?.includes("application/json")) throw new Error("Sua sessão pode ter expirado. Entre novamente antes de continuar o envio.");
  const json = await response.json();
  if (!response.ok) throw new Error(json.error || "Não foi possível enviar o arquivo.");
  return json;
}
export function VideoUpload({ onUploaded, onBusyChange }: { onUploaded: (url: string, name: string) => void; onBusyChange: (busy: boolean) => void }) {
  const [file, setFile] = useState<File | null>(null);
  const session = useRef<Session | null>(null);
  const cancel = useRef(false);
  const [busy, setBusy] = useState(false);
  const [received, setReceived] = useState(0);
  const [error, setError] = useState("");
  const [complete, setComplete] = useState(false);
  async function upload() {
    if (!file || busy) return;
    setBusy(true); onBusyChange(true); setError(""); cancel.current = false;
    try {
      if (!session.current) session.current = await result(await fetch("/api/admin/uploads", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: file.name, size: file.size }) }));
      const current = session.current!;
      const status = await result(await fetch(`/api/admin/uploads/${current.id}`, { cache: "no-store" }));
      let offset = status.received as number;
      setReceived(offset);
      while (offset < file.size) {
        if (cancel.current) return;
        const part = file.slice(offset, offset + current.chunkSize);
        let next: { received: number } | null = null;
        for (let attempt = 0; attempt < 3; attempt++) {
          try {
            next = await result(await fetch(`/api/admin/uploads/${current.id}`, { method: "PUT", headers: { "Content-Type": "application/octet-stream", "X-Upload-Offset": String(offset), "X-Chunk-Length": String(part.size) }, body: part, signal: AbortSignal.timeout(125_000) }));
            break;
          } catch (failure) {
            if (attempt === 2) throw failure;
            await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));
          }
        }
        if (!next || next.received <= offset || next.received > file.size) throw new Error("O progresso do envio é inválido. Tente continuar.");
        offset = next.received; setReceived(offset);
      }
      if (cancel.current) return;
      const saved = await result(await fetch(`/api/admin/uploads/${current.id}`, { method: "POST" }));
      setComplete(true); onUploaded(saved.url, file.name.replace(/\.mp4$/i, ""));
    } catch (failure) { setError(failure instanceof Error ? failure.message : "Falha no envio. Tente continuar."); }
    finally { setBusy(false); onBusyChange(false); }
  }
  const percent = file ? Math.floor(received / file.size * 100) : 0;
  return <section className="space-y-3 rounded-xl border border-violet-400/20 bg-violet-500/5 p-4" aria-label="Enviar vídeo para o cPanel">
    <div className="flex items-center gap-2 text-sm font-medium"><Upload size={16} className="text-violet-400" />Enviar MP4 para o cPanel</div>
    <p className="text-xs leading-relaxed text-muted-foreground">O arquivo fica no disco da sua hospedagem. A Teable recebe somente o link e as configurações. Para HLS, use o link externo do manifesto.</p>
    <Input aria-label="Arquivo MP4" type="file" accept="video/mp4,.mp4" disabled={busy} onChange={e => { const picked = e.target.files?.[0] || null; setFile(picked); session.current = null; setReceived(0); setComplete(false); setError(""); }} />
    {file && <p className="break-all text-xs text-muted-foreground">{file.name} · {(file.size / 1024 / 1024).toLocaleString("pt-BR", { maximumFractionDigits: 1 })} MB</p>}
    {file && <div className="space-y-1"><progress aria-label="Progresso do envio" max={100} value={percent} className="h-2 w-full accent-violet-500" /><p role="status" className="text-xs text-muted-foreground">{complete ? "Arquivo enviado. Salve o cadastro para incluí-lo na biblioteca." : busy ? `Enviando… ${percent}%` : received ? `Envio pausado em ${percent}%. Mantenha esta janela aberta para continuar.` : "Pronto para enviar."}</p></div>}
    {error && <p role="alert" className="text-xs leading-relaxed text-red-300">{error}</p>}
    <div className="flex flex-wrap gap-2">{!complete && <Button type="button" size="sm" disabled={!file || busy} onClick={upload}>{busy ? <Loader2 size={14} className="animate-spin" /> : <Upload size={14} />}{busy ? "Enviando…" : received ? "Continuar envio" : "Enviar arquivo"}</Button>}{busy && <Button type="button" size="sm" variant="outline" onClick={() => { cancel.current = true; }}><Pause size={14} />Pausar após esta parte</Button>}{complete && <span className="flex items-center gap-2 text-xs text-emerald-300"><CheckCircle2 size={14} />Link preenchido abaixo</span>}</div>
    <p className="text-[10px] leading-relaxed text-muted-foreground">Envio em partes de 4 MB. Fechar a página interrompe o envio. Um arquivo concluído permanece no cPanel mesmo se você cancelar o cadastro.</p>
  </section>;
}
