import { useState, useCallback, useRef } from "react";
import { AgGridReact } from "ag-grid-react";
import {
	useDirectoryListing,
	useFfprobe,
	useJobTemplates,
	useRunJob,
} from "../hooks/useFiles";

interface DisplayRow {
	type: string;
	name: string;
	ext: string;
	size: string;
	modified: string;
	path: string;
}

function formatSize(bytes: number): string {
	if (bytes === 0) return "-";
	const units = ["B", "KB", "MB", "GB", "TB"];
	let value = bytes;
	let unitIdx = 0;
	while (value >= 1000 && unitIdx < units.length - 1) {
		value /= 1000;
		unitIdx++;
	}
	return `${value.toFixed(1)} ${units[unitIdx]}`;
}

function formatTime(epoch: number): string {
	if (!epoch) return "";
	return new Date(epoch * 1000).toLocaleString();
}

function isVideoFile(name: string): boolean {
	const exts = [
		".mkv",
		".mp4",
		".avi",
		".m4v",
		".ts",
		".wmv",
		".mov",
		".flv",
		".webm",
	];
	return exts.some((ext) => name.toLowerCase().endsWith(ext));
}

export function FileBrowser() {
	const [currentDir, setCurrentDir] = useState("/");
	const [pathInput, setPathInput] = useState("/");
	const [selectedPath, setSelectedPath] = useState<string | null>(null);

	const { data: listing, isLoading, error } = useDirectoryListing(currentDir);
	const { data: ffprobeData } = useFfprobe(
		selectedPath ?? "",
		!!selectedPath && isVideoFile(selectedPath),
	);
	const { data: templates } = useJobTemplates();
	const runJob = useRunJob();

	const gridRef = useRef<AgGridReact<DisplayRow>>(null);

	const navigate = useCallback((path: string) => {
		setCurrentDir(path);
		setPathInput(path);
		setSelectedPath(null);
	}, []);

	const handlePathSubmit = (e: React.KeyboardEvent) => {
		if (e.key === "Enter") {
			navigate(pathInput || "/");
		}
	};

	// Build display rows
	const rows: DisplayRow[] = [];
	if (currentDir !== "/") {
		const parent = currentDir.replace(/\/[^/]+\/?$/, "") || "/";
		rows.push({
			type: "up",
			name: "..",
			ext: "",
			size: "-",
			modified: "",
			path: parent,
		});
	}
	if (listing) {
		for (const entry of listing.entries) {
			const kind = entry.type === "d" ? "dir" : "file";
			const ext = kind === "file" ? (entry.name.split(".").pop() ?? "") : "";
			rows.push({
				type: kind,
				name: entry.name,
				ext,
				size: kind === "dir" ? "-" : formatSize(entry.size),
				modified: formatTime(entry.mtime),
				path: `${currentDir === "/" ? "" : currentDir}/${entry.name}`,
			});
		}
	}

	const columnDefs = [
		{ field: "type" as const, headerName: "Type", width: 80 },
		{ field: "name" as const, headerName: "Name", flex: 2 },
		{ field: "ext" as const, headerName: "Ext", width: 80 },
		{ field: "size" as const, headerName: "Size", width: 110 },
		{ field: "modified" as const, headerName: "Modified", width: 180 },
	];

	const onRowClicked = useCallback(
		(event: { data?: DisplayRow }) => {
			const row = event.data;
			if (!row) return;
			if (row.type === "dir" || row.type === "up") {
				navigate(row.path);
			} else {
				setSelectedPath(row.path);
			}
		},
		[navigate],
	);

	return (
		<div className="space-y-4">
			{/* Path input */}
			<div className="flex gap-2">
				<input
					type="text"
					value={pathInput}
					onChange={(e) => setPathInput(e.target.value)}
					onKeyDown={handlePathSubmit}
					className="border rounded px-3 py-1 text-sm flex-1"
					placeholder="Remote path (press Enter to navigate)"
				/>
				<button
					onClick={() => navigate(pathInput || "/")}
					className="px-3 py-1 text-sm rounded border hover:bg-gray-50"
				>
					Refresh
				</button>
			</div>

			{/* Status */}
			<div className="flex gap-6 text-xs text-gray-500">
				<span>
					Current: <code>{currentDir}</code>
				</span>
				{selectedPath && (
					<span>
						Selected: <code>{selectedPath}</code>
					</span>
				)}
				{listing && <span>Entries: {listing.count}</span>}
			</div>

			{error && <p className="text-sm text-red-600">Error: {String(error)}</p>}

			{/* File listing grid */}
			<div className="ag-theme-alpine" style={{ height: 400, width: "100%" }}>
				<AgGridReact<DisplayRow>
					ref={gridRef}
					rowData={rows}
					columnDefs={columnDefs}
					rowSelection="single"
					onRowClicked={onRowClicked}
					loading={isLoading}
					suppressCellFocus
					animateRows={false}
				/>
			</div>

			{/* ffprobe preview */}
			{selectedPath && isVideoFile(selectedPath) && (
				<section className="border rounded-lg p-4">
					<h3 className="text-sm font-semibold mb-2">
						ffprobe preview: <code className="text-xs">{selectedPath}</code>
					</h3>
					{ffprobeData ? (
						<pre className="text-xs bg-gray-50 p-3 rounded overflow-auto max-h-96">
							{JSON.stringify(ffprobeData, null, 2)}
						</pre>
					) : (
						<p className="text-sm text-gray-500">Loading ffprobe data...</p>
					)}
				</section>
			)}

			{/* Jobs */}
			{selectedPath && templates && templates.length > 0 && (
				<section className="border rounded-lg p-4">
					<h3 className="text-sm font-semibold mb-2">Jobs</h3>
					<div className="flex gap-2 flex-wrap">
						{templates.map((tpl) => (
							<button
								key={tpl.key}
								onClick={() =>
									runJob.mutate({ jobKey: tpl.key, path: selectedPath })
								}
								className="px-3 py-1 text-sm rounded border hover:bg-gray-50"
								title={tpl.description}
							>
								{tpl.name}
							</button>
						))}
					</div>
					{runJob.data && (
						<pre className="text-xs bg-gray-50 p-3 rounded mt-3 overflow-auto max-h-48">
							Exit: {runJob.data.exit_status}
							{"\n"}
							{runJob.data.stdout}
							{runJob.data.stderr && `\nSTDERR: ${runJob.data.stderr}`}
						</pre>
					)}
				</section>
			)}
		</div>
	);
}
