"use client";

/**
 * VideoUploader — direct-to-R2 (S3) video upload sa progress bar-om.
 *
 * Tok:
 *   1. Korisnik bira MP4 / WebM / MOV fajl iz file picker-a
 *   2. POST na /api/admin/media/presigned-upload za PUT URL
 *   3. PUT direktno na R2 (zaobilazi Vercel 4.5MB body limit)
 *   4. POST na /api/admin/media/register da kreiramo Media record
 *   5. onUploaded callback dobija { id, url } — roditelj koristi URL
 *      kao videoUrl ili Media.id po potrebi
 */

import { useRef, useState } from "react";

type UploadResult = {
  id: string;
  url: string;
};

const ACCEPTED_VIDEO_MIMES = [
  "video/mp4",
  "video/webm",
  "video/quicktime",
];

const MAX_BYTES = 500 * 1024 * 1024; // 500 MB

function formatBytes(bytes: number): string {
  if (bytes >= 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
  if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
  if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
  return `${bytes} B`;
}

export function VideoUploader({
  directory = "videos",
  onUploaded,
  hint,
}: {
  /** Folder na R2 (npr. „events/{id}/video"). */
  directory?: string;
  /** Pozove se kad upload uspe — daje URL koji ide u Media DB. */
  onUploaded?: (result: UploadResult) => void;
  /** Opcioni helper tekst ispod uploader-a. */
  hint?: string;
}) {
  const [file, setFile] = useState<File | null>(null);
  const [stage, setStage] = useState<
    "idle" | "presigning" | "uploading" | "registering" | "done" | "error"
  >("idle");
  const [progress, setProgress] = useState(0);
  const [message, setMessage] = useState<string | null>(null);
  const [result, setResult] = useState<UploadResult | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);

  function pickFile(picked: File | null) {
    if (!picked) return;
    if (!ACCEPTED_VIDEO_MIMES.includes(picked.type)) {
      setMessage(
        `Nedozvoljen format. Dozvoljeno: MP4, WebM, MOV. Dobijen: ${picked.type || "nepoznat"}.`,
      );
      return;
    }
    if (picked.size > MAX_BYTES) {
      setMessage(`Fajl je veći od ${formatBytes(MAX_BYTES)}. Smanji rezoluciju ili duzinu.`);
      return;
    }
    setFile(picked);
    setMessage(null);
    setStage("idle");
    setProgress(0);
    setResult(null);
  }

  async function startUpload() {
    if (!file) return;
    setMessage(null);
    setResult(null);

    try {
      // ── Korak 1: traži presigned URL ────────────────────────────
      setStage("presigning");
      setMessage("Pripremam upload…");

      const presignRes = await fetch("/api/admin/media/presigned-upload", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          filename: file.name,
          mimeType: file.type,
          fileSize: file.size,
          directory,
        }),
      });

      const presignText = await presignRes.text();
      let presign: { uploadUrl?: string; publicUrl?: string; message?: string } = {};
      try {
        presign = presignText ? JSON.parse(presignText) : {};
      } catch {
        throw new Error(`Server greška pri pripremi upload-a (HTTP ${presignRes.status}).`);
      }
      if (!presignRes.ok || !presign.uploadUrl || !presign.publicUrl) {
        throw new Error(presign.message || "Nije dobijen upload URL.");
      }

      // ── Korak 2: PUT direktno na R2 sa XHR za progress ──────────
      setStage("uploading");
      setMessage(`Uploadujem ${formatBytes(file.size)}…`);
      setProgress(0);

      const uploadUrl = presign.uploadUrl;
      await new Promise<void>((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("PUT", uploadUrl, true);
        xhr.setRequestHeader("Content-Type", file.type);
        xhr.upload.onprogress = (e) => {
          if (e.lengthComputable) setProgress(Math.round((e.loaded / e.total) * 100));
        };
        xhr.onload = () => {
          if (xhr.status >= 200 && xhr.status < 300) resolve();
          else reject(new Error(`Upload pukao na storage (HTTP ${xhr.status}).`));
        };
        xhr.onerror = () => reject(new Error("Network greška tokom upload-a."));
        xhr.send(file);
      });

      // ── Korak 3: registruj u Media tabeli ───────────────────────
      setStage("registering");
      setMessage("Registrujem u biblioteci…");

      const registerRes = await fetch("/api/admin/media/register", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          url: presign.publicUrl,
          mimeType: file.type,
          fileSize: file.size,
          alt: file.name,
        }),
      });

      const registerData = (await registerRes.json()) as {
        id?: string;
        url?: string;
        message?: string;
      };

      if (!registerRes.ok || !registerData.id || !registerData.url) {
        throw new Error(registerData.message || "Registracija u biblioteci nije uspela.");
      }

      const uploadResult: UploadResult = { id: registerData.id, url: registerData.url };
      setStage("done");
      setMessage(`Video uspešno uploadovan (${formatBytes(file.size)}).`);
      setResult(uploadResult);
      onUploaded?.(uploadResult);
    } catch (err) {
      setStage("error");
      setMessage(err instanceof Error ? err.message : "Nepoznata greška.");
    }
  }

  function reset() {
    setFile(null);
    setStage("idle");
    setProgress(0);
    setMessage(null);
    setResult(null);
    if (inputRef.current) inputRef.current.value = "";
  }

  return (
    <div className="rounded-2xl border border-dashed border-border bg-white/70 p-5">
      <input
        ref={inputRef}
        type="file"
        accept={ACCEPTED_VIDEO_MIMES.join(",")}
        onChange={(e) => pickFile(e.target.files?.[0] ?? null)}
        className="sr-only"
      />

      {!file ? (
        <button
          type="button"
          onClick={() => inputRef.current?.click()}
          className="flex w-full flex-col items-center justify-center gap-3 rounded-xl py-8 text-center transition hover:bg-[#fff4f0]"
        >
          <div className="flex h-12 w-12 items-center justify-center rounded-xl bg-[#fff4f0]">
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#c2410c" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <polygon points="23 7 16 12 23 17 23 7" />
              <rect x="1" y="5" width="15" height="14" rx="2" ry="2" />
            </svg>
          </div>
          <div>
            <p className="text-sm font-semibold text-foreground">Klikni za izbor video fajla</p>
            <p className="mt-1 text-xs text-muted-foreground">
              MP4, WebM ili MOV — do {formatBytes(MAX_BYTES)}
            </p>
          </div>
        </button>
      ) : (
        <div className="space-y-3">
          <div className="flex items-start gap-3 rounded-xl border border-border bg-white px-3 py-2.5">
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#c2410c" strokeWidth="2" className="mt-0.5 shrink-0">
              <polygon points="23 7 16 12 23 17 23 7" />
              <rect x="1" y="5" width="15" height="14" rx="2" ry="2" />
            </svg>
            <div className="min-w-0 flex-1">
              <p className="truncate text-sm font-semibold text-foreground">{file.name}</p>
              <p className="text-xs text-muted-foreground">
                {formatBytes(file.size)} • {file.type}
              </p>
            </div>
            {stage === "idle" || stage === "error" ? (
              <button
                type="button"
                onClick={reset}
                className="text-xs font-semibold text-muted-foreground hover:text-foreground"
              >
                Promeni
              </button>
            ) : null}
          </div>

          {stage === "uploading" ? (
            <div className="space-y-1.5">
              <div className="h-2 overflow-hidden rounded-full bg-[#faf9f7]">
                <div
                  className="h-full rounded-full bg-primary transition-all duration-200"
                  style={{ width: `${progress}%` }}
                />
              </div>
              <p className="text-[0.7rem] font-bold text-primary">{progress}%</p>
            </div>
          ) : null}

          {message ? (
            <p
              className={`text-xs ${
                stage === "error"
                  ? "text-red-700"
                  : stage === "done"
                    ? "text-emerald-700"
                    : "text-muted-foreground"
              }`}
            >
              {message}
            </p>
          ) : null}

          {result ? (
            <div className="rounded-xl border border-emerald-200 bg-emerald-50 p-3">
              <p className="text-xs font-bold text-emerald-900">✓ Spremno za korišćenje</p>
              <p className="mt-1 break-all text-[0.7rem] text-emerald-800">{result.url}</p>
            </div>
          ) : null}

          {stage === "idle" || stage === "error" ? (
            <button
              type="button"
              onClick={startUpload}
              className="inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-primary px-5 text-sm font-bold text-white shadow-[0_8px_22px_rgba(194,65,12,0.28)] transition hover:bg-[#d94e22]"
            >
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                <polyline points="17 8 12 3 7 8" />
                <line x1="12" y1="3" x2="12" y2="15" />
              </svg>
              Pokreni upload
            </button>
          ) : null}
        </div>
      )}

      {hint ? <p className="mt-3 text-xs text-muted-foreground">{hint}</p> : null}
    </div>
  );
}
