"use client";

import React, {
    useEffect,
    useMemo,
    useState,
    useCallback,
    useRef,
    MutableRefObject,
} from "react";
import {
    Loader2,
    Download,
    Folder,
    FileText,
    RefreshCw,
    ArrowUp,
    Home,
} from "lucide-react";

type FileItem = {
    name: string;
    type: "dir" | "file";
    size?: number;
    mtimeMs?: number;
};

type ListResponse =
| { path: string; items: FileItem[] }
| { path: string; entries: FileItem[] }
| { items?: FileItem[]; entries?: FileItem[]; path?: string };

const BASE =
(process.env.NEXT_PUBLIC_FILE_API_BASE_URL || "").replace(/\/$/, "") || "";

function joinPath(a: string, b: string) {
    if (!a || a === "/") return b.startsWith("/") ? b : `/${b}`;
    return `${a.replace(/\/$/, "")}/${b.replace(/^\//, "")}`;
}
function parentPath(path: string) {
    if (!path || path === "/") return "/";
    const parts = path.replace(/\/+$/, "").split("/");
    parts.pop();
    const p = parts.join("/");
    return p === "" ? "/" : p;
}
function formatSize(bytes?: number) {
    if (bytes == null) return "—";
    const units = ["B", "KB", "MB", "GB", "TB"];
    let v = bytes;
    let u = 0;
    while (v >= 1024 && u < units.length - 1) {
        v /= 1024;
        u++;
    }
    return `${v.toFixed(u ? 1 : 0)} ${units[u]}`;
}

const LS_KEY = "fs.split.left"; // px

export default function FileBrowserPanel() {
    const [path, setPath] = useState<string>("/");
    const [items, setItems] = useState<FileItem[]>([]);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [previewHref, setPreviewHref] = useState<string | null>(null);

    // ───────────────── Splitter state
    const containerRef = useRef<HTMLDivElement | null>(null);
    const [leftPx, setLeftPx] = useState<number>(() => {
        if (typeof window === "undefined") return 640; // SSR default
        const v = Number(localStorage.getItem(LS_KEY));
        return Number.isFinite(v) && v > 0 ? v : 720; // good desktop start
    });

    // Enforce bounds on resize / first mount
    const clampLeft = useCallback((want: number) => {
        const host = containerRef.current;
        if (!host) return want;
        const total = host.clientWidth || 0;
        const MIN_LEFT = 520; // so Name + columns fit
        const MIN_RIGHT = 360; // keep preview usable
        const maxLeft = Math.max(320, total - MIN_RIGHT);
        return Math.min(Math.max(want, MIN_LEFT), maxLeft);
    }, []);

    useEffect(() => {
        const handle = () => setLeftPx((v) => clampLeft(v));
        window.addEventListener("resize", handle);
        return () => window.removeEventListener("resize", handle);
    }, [clampLeft]);

    useEffect(() => {
        if (typeof window !== "undefined") {
            localStorage.setItem(LS_KEY, String(leftPx));
        }
    }, [leftPx]);

    // ───────────────── Data
    const urlList = useMemo(() => {
        const p = encodeURIComponent(path || "/");
        return `${BASE}/api/files/list?path=${p}`;
    }, [path]);
    const urlDownload = useCallback((p: string) => {
        const qp = encodeURIComponent(p || "/");
        return `${BASE}/api/files/download?path=${qp}`;
    }, []);
    const urlRaw = useCallback((p: string) => {
        const qp = encodeURIComponent(p || "/");
        return `${BASE}/api/files/raw?path=${qp}`;
    }, []);

    const fetchList = useCallback(async () => {
        setLoading(true);
        setError(null);
        setPreviewHref(null);
        try {
            const res = await fetch(urlList, {
                method: "GET",
                credentials: "include",
                headers: { Accept: "application/json" },
                cache: "no-store",
            });
            if (!res.ok) {
                const text = await res.text().catch(() => "");
                throw new Error(text || `HTTP ${res.status}`);
            }
            const json: ListResponse = await res.json();
            const arr = (json as any).items || (json as any).entries || [];
            if (!Array.isArray(arr)) throw new Error("Malformed list response");
            arr.sort((a: FileItem, b: FileItem) => {
                if (a.type !== b.type) return a.type === "dir" ? -1 : 1;
                return a.name.localeCompare(b.name);
            });
            setItems(arr);
        } catch (e: any) {
            setError(e?.message || String(e));
            setItems([]);
        } finally {
            setLoading(false);
        }
    }, [urlList]);

    useEffect(() => {
        fetchList();
    }, [fetchList]);

    // ───────────────── Actions
    const onOpen = (it: FileItem) => {
        if (it.type === "dir") {
            setPath((p) => joinPath(p, it.name));
        } else {
            setPreviewHref(urlRaw(joinPath(path, it.name)));
        }
    };
    const onUp = () => setPath((p) => parentPath(p));
    const onHome = () => setPath("/");
    const onDownload = (it: FileItem) => {
        const href = urlDownload(joinPath(path, it.name));
        const a = document.createElement("a");
        a.href = href;
        a.download = it.name;
        document.body.appendChild(a);
        a.click();
        a.remove();
    };

    // ───────────────── Splitter drag handlers
    const draggingRef = useRef(false);
    const startXRef = useRef(0);
    const startLeftRef = useRef(0);

    const onSplitDown = (e: React.MouseEvent | React.TouchEvent) => {
        draggingRef.current = true;
        startXRef.current =
        "touches" in e ? e.touches[0].clientX : (e as React.MouseEvent).clientX;
        startLeftRef.current = leftPx;
        document.addEventListener("mousemove", onSplitMove as any);
        document.addEventListener("mouseup", onSplitUp as any);
        document.addEventListener("touchmove", onSplitMove as any, { passive: false });
        document.addEventListener("touchend", onSplitUp as any);
    };

    const onSplitMove = (e: MouseEvent | TouchEvent) => {
        if (!draggingRef.current) return;
        const clientX =
        e instanceof TouchEvent ? e.touches[0]?.clientX ?? startXRef.current : e.clientX;
        const dx = clientX - startXRef.current;
        setLeftPx((prev) => clampLeft(startLeftRef.current + dx));
        if (e.cancelable) e.preventDefault();
    };

        const onSplitUp = () => {
            draggingRef.current = false;
            document.removeEventListener("mousemove", onSplitMove as any);
            document.removeEventListener("mouseup", onSplitUp as any);
            document.removeEventListener("touchmove", onSplitMove as any);
            document.removeEventListener("touchend", onSplitUp as any);
        };

        return (
            <div className="space-y-3">
            {/* Small styles */}
            <style>{`
                .split-gutter {
                    width: 8px;
                    cursor: col-resize;
                    user-select: none;
                    touch-action: none;
                    background: transparent;
                }
                .split-gutter:hover { background: rgba(255,255,255,0.06); }
                @media (max-width: 1023px) {
                    .split-wrap { display:block !important; }
                    .split-gutter { display:none; }
                }
                `}</style>

                {/* Toolbar */}
                <div className="flex items-center gap-2">
                <button
                onClick={onHome}
                className="inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm hover:bg-muted"
                title="Root"
                >
                <Home className="h-4 w-4" /> root
                </button>

                <div className="ml-auto flex items-center gap-2">
                <button
                onClick={fetchList}
                className="inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm hover:bg-muted"
                title="Refresh"
                >
                <RefreshCw className="h-4 w-4" /> Refresh
                </button>
                <button
                onClick={onUp}
                className="inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm hover:bg-muted"
                title="Up one folder"
                >
                <ArrowUp className="h-4 w-4" /> Up
                </button>
                </div>
                </div>

                <div className="text-xs text-muted-foreground select-all">{path || "/"}</div>

                {/* Split container */}
                <div
                ref={containerRef}
                className="split-wrap flex w-full gap-0 rounded-md border"
                style={{ overflow: "hidden" }}
                >
                {/* LEFT: table */}
                <div
                className="min-w-[520px] border-r"
                style={{ width: leftPx, overflow: "hidden" }}
                >
                <div className="overflow-x-auto">
                <div className="min-w-[760px]">
                {/* Header: name flexes; others compact so Actions never truncates */}
                <div className="grid grid-cols-[minmax(320px,1fr),90px,96px,184px,120px] items-center bg-muted px-3 py-2 text-sm font-medium">
                <div>Name</div>
                <div>Type</div>
                <div>Size</div>
                <div>Modified</div>
                <div className="text-right">Actions</div>
                </div>

                <div className="divide-y">
                {loading ? (
                    <div className="p-6 text-sm text-muted-foreground flex items-center gap-2">
                    <Loader2 className="h-4 w-4 animate-spin" /> Loading…
                    </div>
                ) : error ? (
                    <div className="p-6 text-sm text-rose-400">Error: {error}</div>
                ) : items.length === 0 ? (
                    <div className="p-6 text-sm text-muted-foreground">Empty folder.</div>
                ) : (
                    items.map((it) => (
                        <div
                        key={it.name + it.type}
                        className="grid grid-cols-[minmax(320px,1fr),90px,96px,184px,120px] items-center px-3 py-2 text-sm hover:bg-muted/50"
                        >
                        <button
                        className="text-left inline-flex items-center gap-2 hover:underline min-w-0"
                        onClick={() => onOpen(it)}
                        title={it.type === "dir" ? "Open folder" : "Preview"}
                        >
                        {it.type === "dir" ? (
                            <Folder className="h-4 w-4 shrink-0" />
                        ) : (
                            <FileText className="h-4 w-4 shrink-0" />
                        )}
                        <span className="truncate">{it.name}</span>
                        </button>
                        <div className="uppercase tracking-wide text-[11px] text-muted-foreground">
                        {it.type}
                        </div>
                        <div className="text-muted-foreground">{formatSize(it.size)}</div>
                        <div className="text-muted-foreground">
                        {it.mtimeMs ? new Date(it.mtimeMs).toLocaleString() : "—"}
                        </div>
                        <div className="text-right">
                        {it.type === "file" && (
                            <button
                            onClick={() => onDownload(it)}
                            className="inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs hover:bg-muted"
                            title="Download"
                            >
                            <Download className="h-3.5 w-3.5" />
                            Download
                            </button>
                        )}
                        </div>
                        </div>
                    ))
                )}
                </div>
                </div>
                </div>
                </div>

                {/* GUTTER */}
                <div
                className="split-gutter"
                onMouseDown={onSplitDown as any}
                onTouchStart={onSplitDown as any}
                aria-label="Resize panels"
                role="separator"
                aria-orientation="vertical"
                />

                {/* RIGHT: preview */}
                <div className="min-w-[360px] flex-1" style={{ minHeight: 0 }}>
                <div className="p-3" style={{ height: "100%" }}>
                <div className="mb-2 text-sm font-medium">Preview</div>
                <div className="border rounded overflow-hidden" style={{ height: 420 }}>
                {previewHref ? (
                    <iframe
                    key={previewHref}
                    src={previewHref}
                    className="w-full h-full"
                    title="Preview"
                    />
                ) : (
                    <div className="p-3 text-sm text-muted-foreground">
                    Select a file to preview.
                    </div>
                )}
                </div>
                </div>
                </div>
                </div>
                </div>
        );
}
