"use client";

import { useState } from "react";
import { OcTransitionUpIcon } from "@opencut/ui/icons";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { Button } from "../ui/button";
import { Label } from "../ui/label";
import { RadioGroup, RadioGroupItem } from "../ui/radio-group";
import { Progress } from "../ui/progress";
import { Checkbox } from "../ui/checkbox";
import { cn } from "@/utils/ui";
import { getExportMimeType, getExportFileExtension } from "@/lib/export";
import { Check, Copy, Download, RotateCcw, X } from "lucide-react";
import {
	EXPORT_FORMAT_VALUES,
	EXPORT_QUALITY_VALUES,
	type ExportFormat,
	type ExportQuality,
	type ExportResult,
} from "@/types/export";
import { PropertyGroup } from "./properties-panel/property-item";
import { useEditor } from "@/hooks/use-editor";
import { DEFAULT_EXPORT_OPTIONS } from "@/constants/export-constants";

export function ExportButton() {
	const [isExportPopoverOpen, setIsExportPopoverOpen] = useState(false);
	const editor = useEditor();

	const handleExport = () => {
		setIsExportPopoverOpen(true);
	};

	const hasProject = !!editor.project.getActive();

	return (
		<Popover open={isExportPopoverOpen} onOpenChange={setIsExportPopoverOpen}>
			<PopoverTrigger asChild>
				<button
					type="button"
					className={cn(
						"flex items-center gap-1.5 rounded-md bg-[#38BDF8] px-[0.12rem] py-[0.12rem] text-white transition-all duration-200",
						hasProject
							? "cursor-pointer hover:brightness-95"
							: "cursor-not-allowed opacity-50",
					)}
					onClick={hasProject ? handleExport : undefined}
					disabled={!hasProject}
					onKeyDown={(event) => {
						if (hasProject && (event.key === "Enter" || event.key === " ")) {
							event.preventDefault();
							handleExport();
						}
					}}
				>
					<div className="relative flex items-center gap-1.5 rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7] px-4 py-1 shadow-[0_1px_3px_0px_rgba(0,0,0,0.65)]">
						<OcTransitionUpIcon className="z-50" />
						<span className="z-50 text-[0.875rem]">Export</span>
						<div className="absolute top-0 left-0 z-10 flex size-full items-center justify-center rounded-[0.8rem] bg-linear-to-t from-white/0 to-white/50">
							<div className="absolute top-[0.08rem] z-50 h-[calc(100%-2px)] w-[calc(100%-2px)] rounded-[0.8rem] bg-linear-270 from-[#2567EC] to-[#37B6F7]"></div>
						</div>
					</div>
				</button>
			</PopoverTrigger>
			{hasProject && <ExportPopover onOpenChange={setIsExportPopoverOpen} />}
		</Popover>
	);
}

function ExportPopover({
	onOpenChange,
}: {
	onOpenChange: (open: boolean) => void;
}) {
	const editor = useEditor();
	const activeProject = editor.project.getActive();
	const [format, setFormat] = useState<ExportFormat>(
		DEFAULT_EXPORT_OPTIONS.format,
	);
	const [quality, setQuality] = useState<ExportQuality>(
		DEFAULT_EXPORT_OPTIONS.quality,
	);
	const [includeAudio, setIncludeAudio] = useState<boolean>(
		DEFAULT_EXPORT_OPTIONS.includeAudio || true,
	);
	const [isExporting, setIsExporting] = useState(false);
	const [progress, setProgress] = useState(0);
	const [exportResult, setExportResult] = useState<ExportResult | null>(null);

	const handleExport = async () => {
		if (!activeProject) return;

		setIsExporting(true);
		setProgress(0);
		setExportResult(null);

		const result = await editor.project.export({
			options: {
				format,
				quality,
				fps: activeProject.settings.fps,
				includeAudio,
				onProgress: ({ progress }) => setProgress(progress),
				onCancel: () => false, // TODO: add cancel functionality
			},
		});

		setIsExporting(false);
		setExportResult(result);

		if (result.success && result.buffer) {
			const mimeType = getExportMimeType({ format });
			const extension = getExportFileExtension({ format });
			const blob = new Blob([result.buffer], { type: mimeType });
			const url = URL.createObjectURL(blob);

			const a = document.createElement("a");
			a.href = url;
			a.download = `${activeProject.metadata.name}${extension}`;
			document.body.appendChild(a);
			a.click();
			document.body.removeChild(a);
			URL.revokeObjectURL(url);

			onOpenChange(false);
			setExportResult(null);
			setProgress(0);
		}
	};

	const handleClose = () => {
		if (!isExporting) {
			onOpenChange(false);
			setExportResult(null);
			setProgress(0);
		}
	};

	return (
		<PopoverContent className="bg-background mr-4 flex w-80 flex-col gap-3">
			{exportResult && !exportResult.success ? (
				<ExportError
					error={exportResult.error || "Unknown error occurred"}
					onRetry={handleExport}
				/>
			) : (
				<>
					<div className="flex items-center justify-between">
						<h3 className="font-medium">
							{isExporting ? "Exporting project" : "Export project"}
						</h3>
						<Button variant="text" size="icon" onClick={handleClose}>
							<X className="text-foreground/85 !size-5" />
						</Button>
					</div>

					<div className="flex flex-col gap-4">
						{!isExporting && (
							<>
								<div className="flex flex-col gap-3">
									<PropertyGroup
										title="Format"
										titleClassName="text-sm"
										defaultExpanded={false}
									>
										<RadioGroup
											value={format}
											onValueChange={(value) => {
												if (isExportFormat(value)) {
													setFormat(value);
												}
											}}
										>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="mp4" id="mp4" />
												<Label htmlFor="mp4">
													MP4 (H.264) - Better compatibility
												</Label>
											</div>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="webm" id="webm" />
												<Label htmlFor="webm">
													WebM (VP9) - Smaller file size
												</Label>
											</div>
										</RadioGroup>
									</PropertyGroup>

									<PropertyGroup
										title="Quality"
										titleClassName="text-sm"
										defaultExpanded={false}
									>
										<RadioGroup
											value={quality}
											onValueChange={(value) => {
												if (isExportQuality(value)) {
													setQuality(value);
												}
											}}
										>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="low" id="low" />
												<Label htmlFor="low">Low - Smallest file size</Label>
											</div>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="medium" id="medium" />
												<Label htmlFor="medium">Medium - Balanced</Label>
											</div>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="high" id="high" />
												<Label htmlFor="high">High - Recommended</Label>
											</div>
											<div className="flex items-center space-x-2">
												<RadioGroupItem value="very_high" id="very_high" />
												<Label htmlFor="very_high">
													Very High - Largest file size
												</Label>
											</div>
										</RadioGroup>
									</PropertyGroup>

									<PropertyGroup
										title="Audio"
										titleClassName="text-sm"
										defaultExpanded={false}
									>
										<div className="flex items-center space-x-2">
											<Checkbox
												id="include-audio"
												checked={includeAudio}
												onCheckedChange={(checked) =>
													setIncludeAudio(!!checked)
												}
											/>
											<Label htmlFor="include-audio">
												Include audio in export
											</Label>
										</div>
									</PropertyGroup>
								</div>

								<Button onClick={handleExport} className="w-full gap-2">
									<Download className="size-4" />
									Export
								</Button>
							</>
						)}

						{isExporting && (
							<div className="space-y-4">
								<div className="flex flex-col">
									<div className="flex items-center justify-between text-center">
										<p className="text-muted-foreground mb-2 text-sm">
											{Math.round(progress * 100)}%
										</p>
										<p className="text-muted-foreground mb-2 text-sm">100%</p>
									</div>
									<Progress value={progress * 100} className="w-full" />
								</div>

								<Button
									variant="outline"
									className="w-full rounded-md"
									onClick={() => {}}
								>
									Cancel
								</Button>
							</div>
						)}
					</div>
				</>
			)}
		</PopoverContent>
	);
}

function isExportFormat(value: string): value is ExportFormat {
	return EXPORT_FORMAT_VALUES.some((formatValue) => formatValue === value);
}

function isExportQuality(value: string): value is ExportQuality {
	return EXPORT_QUALITY_VALUES.some((qualityValue) => qualityValue === value);
}

function ExportError({
	error,
	onRetry,
}: {
	error: string;
	onRetry: () => void;
}) {
	const [copied, setCopied] = useState(false);

	const handleCopy = async () => {
		await navigator.clipboard.writeText(error);
		setCopied(true);
		setTimeout(() => setCopied(false), 1000);
	};

	return (
		<div className="space-y-4">
			<div className="flex flex-col gap-1.5">
				<p className="text-destructive text-sm font-medium">Export failed</p>
				<p className="text-muted-foreground text-xs">{error}</p>
			</div>

			<div className="flex gap-2">
				<Button
					variant="outline"
					size="sm"
					className="h-8 flex-1 text-xs"
					onClick={handleCopy}
				>
					{copied ? <Check className="text-constructive" /> : <Copy />}
					Copy
				</Button>
				<Button
					variant="outline"
					size="sm"
					className="h-8 flex-1 text-xs"
					onClick={onRetry}
				>
					<RotateCcw />
					Retry
				</Button>
			</div>
		</div>
	);
}
