import { useState, useCallback, type FormEvent } from "react";
import { uploadVideoInit, uploadVideoComplete } from "../api/client";

function UploadDropzone({
    accept,
    label,
    sublabel,
    required,
    file,
    onFileChange,
}: {
    accept: string;
    label: string;
    sublabel?: string;
    required?: boolean;
    file: File | null;
    onFileChange: (file: File | null) => void;
}) {
    const [isDragOver, setIsDragOver] = useState(false);

    const handleDrop = useCallback(
        (e: React.DragEvent) => {
            e.preventDefault();
            setIsDragOver(false);
            const dropped = e.dataTransfer.files[0];
            if (dropped) onFileChange(dropped);
        },
        [onFileChange],
    );

    return (
        <div>
            <label className="block text-[10px] font-semibold uppercase tracking-[0.15em] text-white/35 mb-2">
                {label} {required && <span className="text-red-400/50">*</span>}
            </label>
            <div
                onDragOver={(e) => {
                    e.preventDefault();
                    setIsDragOver(true);
                }}
                onDragLeave={() => setIsDragOver(false)}
                onDrop={handleDrop}
                onClick={() => {
                    const input = document.createElement("input");
                    input.type = "file";
                    input.accept = accept;
                    input.onchange = () =>
                        onFileChange(input.files?.[0] ?? null);
                    input.click();
                }}
                className={`relative cursor-pointer rounded-lg border-2 border-dashed transition-all duration-200
                    ${
                        file
                            ? "border-mom-accent/40 bg-mom-accent/5"
                            : isDragOver
                              ? "border-mom-accent/40 bg-mom-accent/5"
                              : "border-white/7 bg-white/2 hover:border-white/15 hover:bg-white/3"
                    }
                `}
            >
                <div className="px-5 py-6 text-center">
                    {file ? (
                        <div className="flex flex-col items-center gap-1.5">
                            <svg
                                className="w-5 h-5 text-mom-accent"
                                fill="none"
                                stroke="currentColor"
                                viewBox="0 0 24 24"
                            >
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={2}
                                    d="M5 13l4 4L19 7"
                                />
                            </svg>
                            <span className="text-sm text-white/70 font-medium truncate max-w-full">
                                {file.name}
                            </span>
                            <span className="text-[10px] text-white/25">
                                {(file.size / 1024 / 1024).toFixed(1)} MB -
                                click or drop to replace
                            </span>
                        </div>
                    ) : (
                        <div className="flex flex-col items-center gap-1.5">
                            <svg
                                className="w-6 h-6 text-white/15"
                                fill="none"
                                stroke="currentColor"
                                viewBox="0 0 24 24"
                            >
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    strokeWidth={1.5}
                                    d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
                                />
                            </svg>
                            <span className="text-sm text-white/30">
                                Drop file here or click to browse
                            </span>
                            {sublabel && (
                                <span className="text-[10px] text-white/15">
                                    {sublabel}
                                </span>
                            )}
                        </div>
                    )}
                </div>
            </div>
            {file && (
                <button
                    type="button"
                    onClick={(e) => {
                        e.stopPropagation();
                        onFileChange(null);
                    }}
                    className="mt-1.5 text-[10px] text-white/20 hover:text-red-400/60 transition-colors"
                >
                    Remove
                </button>
            )}
        </div>
    );
}

function ProgressBar({
    progress,
    uploading,
}: {
    progress: number;
    uploading: boolean;
}) {
    if (!uploading) return null;
    return (
        <div className="w-full rounded-full bg-white/5 h-2 overflow-hidden">
            <div
                className="h-full bg-mom-accent rounded-full transition-all duration-300 ease-out"
                style={{ width: `${Math.min(progress, 100)}%` }}
            />
        </div>
    );
}

export default function UploadForm() {
    const [authed, setAuthed] = useState(
        () => !!localStorage.getItem("admin_token"),
    );
    const [tokenInput, setTokenInput] = useState("");
    const [authError, setAuthError] = useState<string | null>(null);

    const [videoFile, setVideoFile] = useState<File | null>(null);
    const [mtvFile, setMtvFile] = useState<File | null>(null);
    const [uploading, setUploading] = useState(false);
    const [progress, setProgress] = useState(0);
    const [error, setError] = useState<string | null>(null);
    const [success, setSuccess] = useState(false);

    const handleAuth = (e: FormEvent) => {
        e.preventDefault();
        if (!tokenInput.trim()) return;

        localStorage.setItem("admin_token", tokenInput.trim());
        setAuthError(null);

        fetch("/api/videos/upload-url", {
            method: "POST",
            headers: { Authorization: `Bearer ${tokenInput.trim()}` },
        })
            .then((res) => {
                if (res.status === 401) {
                    localStorage.removeItem("admin_token");
                    setAuthError("Invalid token");
                    setAuthed(false);
                } else {
                    setAuthed(true);
                }
            })
            .catch(() => {
                setAuthed(true);
            });
    };

    const handleLogout = () => {
        localStorage.removeItem("admin_token");
        setAuthed(false);
        setTokenInput("");
    };

    if (!authed) {
        return (
            <div className="max-w-2xl mx-auto">
                <div className="mb-10">
                    <h1 className="text-3xl font-bold tracking-tight text-white/90 mb-2">
                        Upload Surf Run
                    </h1>
                    <p className="text-sm text-white/30 leading-relaxed">
                        Authenticate to access the upload page.
                    </p>
                </div>

                {authError && (
                    <div className="mb-5 p-4 rounded-lg border border-red-500/20 bg-red-500/5 text-red-400/80 text-sm">
                        {authError}
                    </div>
                )}

                <form onSubmit={handleAuth} className="space-y-4">
                    <div>
                        <label className="block text-[10px] font-semibold uppercase tracking-[0.15em] text-white/35 mb-2">
                            Admin Token
                        </label>
                        <input
                            type="password"
                            value={tokenInput}
                            onChange={(e) => setTokenInput(e.target.value)}
                            placeholder="Enter admin token"
                            className="w-full rounded-lg border border-white/7 bg-white/3 px-4 py-2.5 text-sm text-white/80 placeholder:text-white/15 focus:border-mom-accent/40 focus:outline-none transition-colors"
                        />
                    </div>
                    <button
                        type="submit"
                        className="w-full rounded-lg bg-mom-accent/15 border border-mom-accent/25 px-4 py-3 text-sm font-semibold text-mom-accent hover:bg-mom-accent/25 hover:border-mom-accent/35 transition-all duration-200"
                    >
                        Authenticate
                    </button>
                </form>
            </div>
        );
    }

    const handleSubmit = async (e: FormEvent) => {
        e.preventDefault();
        if (!videoFile || !mtvFile) {
            setError("Video and .mtv files are required");
            return;
        }

        setError(null);
        setUploading(true);
        setSuccess(false);
        setProgress(0);

        try {
            setProgress(5);
            const runDate = mtvFile.lastModified
                ? new Date(mtvFile.lastModified).toISOString()
                : undefined;

            const initRes = await uploadVideoInit(
                mtvFile,
                videoFile.name,
                videoFile.type || "video/webm",
                videoFile.size.toString(),
                runDate,
            );

            const { parts, uploadId } = initRes.presignedUrls;
            const totalSize = videoFile.size;
            const CHUNK_SIZE = 80 * 1024 * 1024;
            const uploadedParts: { partNumber: number; eTag: string }[] = [];

            for (let i = 0; i < parts.length; i++) {
                const part = parts[i]!;
                const start = i * CHUNK_SIZE;
                const end = Math.min(start + CHUNK_SIZE, totalSize);
                const chunk = videoFile.slice(start, end);

                const eTag = await new Promise<string>((resolve, reject) => {
                    const xhr = new XMLHttpRequest();
                    xhr.upload.addEventListener("progress", (e) => {
                        if (e.lengthComputable) {
                            const chunkProgress = e.loaded / e.total;
                            const overallUploaded = start + e.loaded;
                            setProgress(
                                5 +
                                    Math.round(
                                        (overallUploaded / totalSize) * 90,
                                    ),
                            );
                        }
                    });
                    xhr.addEventListener("load", () => {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            const etag = xhr.getResponseHeader("ETag");
                            if (etag) resolve(etag);
                            else
                                reject(
                                    new Error("No ETag returned from upload"),
                                );
                        } else {
                            reject(
                                new Error(
                                    `Upload failed with status ${xhr.status}`,
                                ),
                            );
                        }
                    });
                    xhr.addEventListener("error", () =>
                        reject(new Error("Upload failed")),
                    );
                    xhr.open("PUT", part.url);
                    xhr.setRequestHeader(
                        "Content-Type",
                        videoFile.type || "video/webm",
                    );
                    xhr.send(chunk);
                });

                uploadedParts.push({ partNumber: part.partNumber, eTag });
            }

            setProgress(98);
            await uploadVideoComplete(initRes.id, uploadedParts, uploadId);
            setProgress(100);

            setSuccess(true);
            setVideoFile(null);
            setMtvFile(null);
        } catch (err: any) {
            setError(err.message || "Upload failed");
        } finally {
            setUploading(false);
        }
    };

    return (
        <div className="max-w-2xl mx-auto">
            <div className="mb-10 flex items-start justify-between">
                <div>
                    <h1 className="text-3xl font-bold tracking-tight text-white/90 mb-2">
                        Upload Surf Run
                    </h1>
                    <p className="text-sm text-white/30 leading-relaxed">
                        Drop your replay video and .mtv file. Map name, player,
                        run time, and stage splits are parsed from the .mtv
                        automatically. The run date is taken from the .mtv file.
                    </p>
                </div>
                <button
                    onClick={handleLogout}
                    className="text-[10px] uppercase tracking-[0.15em] text-white/20 hover:text-white/50 transition-colors shrink-0 mt-2"
                >
                    Logout
                </button>
            </div>

            {error && (
                <div className="mb-5 p-4 rounded-lg border border-red-500/20 bg-red-500/5 text-red-400/80 text-sm flex items-start gap-3">
                    <svg
                        className="w-4 h-4 mt-0.5 shrink-0 text-red-400/60"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                    >
                        <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            strokeWidth={2}
                            d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                        />
                    </svg>
                    <span>{error}</span>
                </div>
            )}

            {success && (
                <div className="mb-5 p-4 rounded-lg border border-green-500/20 bg-green-500/5 text-green-400/80 text-sm flex items-start gap-3">
                    <svg
                        className="w-4 h-4 mt-0.5 shrink-0 text-green-400/60"
                        fill="none"
                        stroke="currentColor"
                        viewBox="0 0 24 24"
                    >
                        <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            strokeWidth={2}
                            d="M5 13l4 4L19 7"
                        />
                    </svg>
                    <span>
                        Upload successful. .mtv metadata parsed automatically.
                    </span>
                </div>
            )}

            <form onSubmit={handleSubmit} className="space-y-8">
                <div className="rounded-xl border border-white/7 bg-white/2 p-6 space-y-5">
                    <h2 className="text-xs font-semibold uppercase tracking-[0.15em] text-white/35 mb-1">
                        Files
                    </h2>

                    <UploadDropzone
                        accept="video/*"
                        label="Video"
                        sublabel="MP4, WebM, etc."
                        required
                        file={videoFile}
                        onFileChange={setVideoFile}
                    />

                    <UploadDropzone
                        accept=".mtv"
                        label=".mtv Replay"
                        sublabel="Momentum Mod replay file"
                        required
                        file={mtvFile}
                        onFileChange={setMtvFile}
                    />
                </div>

                {uploading && (
                    <div className="space-y-2">
                        <div className="flex justify-between text-xs text-white/40">
                            <span>
                                {success ? "Complete!" : "Uploading..."}
                            </span>
                            <span>{progress}%</span>
                        </div>
                        <ProgressBar
                            progress={progress}
                            uploading={uploading}
                        />
                    </div>
                )}

                <button
                    type="submit"
                    disabled={uploading || !videoFile || !mtvFile}
                    className="w-full rounded-lg bg-mom-accent/15 border border-mom-accent/25 px-4 py-3 text-sm font-semibold text-mom-accent hover:bg-mom-accent/25 hover:border-mom-accent/35 disabled:opacity-30 disabled:cursor-not-allowed transition-all duration-200"
                >
                    {uploading ? "Uploading..." : "Upload"}
                </button>
            </form>
        </div>
    );
}
