"use client";

import {
	Badge,
	Button,
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
	Dialog,
	DialogContent,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
	Input,
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
	Table,
	TableBody,
	TableCell,
	TableHead,
	TableHeader,
	TableRow,
} from "@mdxui/primitives";
import { cn } from "@mdxui/primitives/lib/utils";
import {
	Copy,
	Edit,
	Eye,
	EyeOff,
	Filter,
	Plus,
	Search,
	Trash2,
} from "lucide-react";
import * as React from "react";
import { toast } from "sonner";
import { SecretForm } from "./secret-form";
import type { Secret, SecretsManagerProps } from "./types";

export function SecretsManager({
	secrets: externalSecrets = [],
	environments = ["development", "staging", "production"],
	currentEnvironment = "development",
	onEnvironmentChange,
	onCreate,
	onUpdate,
	onDelete,
	hideValues: initialHideValues = true,
	editable = true,
	className,
}: SecretsManagerProps) {
	const [localSecrets, setLocalSecrets] = React.useState<Secret[]>([]);
	const [hideValues, setHideValues] = React.useState(initialHideValues);
	const [searchQuery, setSearchQuery] = React.useState("");
	const [environment, setEnvironment] = React.useState(currentEnvironment);
	const [visibleSecrets, setVisibleSecrets] = React.useState<Set<string>>(
		new Set(),
	);
	const [editingSecret, setEditingSecret] = React.useState<Secret | null>(null);
	const [isCreateDialogOpen, setIsCreateDialogOpen] = React.useState(false);
	const [isEditDialogOpen, setIsEditDialogOpen] = React.useState(false);

	const secrets = externalSecrets.length > 0 ? externalSecrets : localSecrets;

	React.useEffect(() => {
		setEnvironment(currentEnvironment);
	}, [currentEnvironment]);

	const filteredSecrets = React.useMemo(() => {
		return secrets.filter((secret) => {
			const matchesSearch = searchQuery
				? secret.key.toLowerCase().includes(searchQuery.toLowerCase()) ||
					secret.description?.toLowerCase().includes(searchQuery.toLowerCase())
				: true;

			const matchesEnvironment =
				environment === "all" || secret.environment === environment;

			return matchesSearch && matchesEnvironment;
		});
	}, [secrets, searchQuery, environment]);

	const handleEnvironmentChange = (newEnvironment: string) => {
		setEnvironment(newEnvironment);
		onEnvironmentChange?.(newEnvironment);
	};

	const handleCreate = async (
		secretData: Omit<Secret, "id" | "createdAt" | "updatedAt">,
	) => {
		const newSecret: Secret = {
			...secretData,
			id: crypto.randomUUID(),
			createdAt: new Date(),
			updatedAt: new Date(),
		};

		try {
			await onCreate?.(secretData);

			if (externalSecrets.length === 0) {
				setLocalSecrets((prev) => [...prev, newSecret]);
			}

			setIsCreateDialogOpen(false);
			toast.success("Secret created successfully");
		} catch (error) {
			toast.error("Failed to create secret");
		}
	};

	const handleUpdate = async (id: string, updates: Partial<Secret>) => {
		try {
			await onUpdate?.(id, { ...updates, updatedAt: new Date() });

			if (externalSecrets.length === 0) {
				setLocalSecrets((prev) =>
					prev.map((secret) =>
						secret.id === id
							? { ...secret, ...updates, updatedAt: new Date() }
							: secret,
					),
				);
			}

			setIsEditDialogOpen(false);
			setEditingSecret(null);
			toast.success("Secret updated successfully");
		} catch (error) {
			toast.error("Failed to update secret");
		}
	};

	const handleDelete = async (id: string) => {
		if (!confirm("Are you sure you want to delete this secret?")) return;

		try {
			await onDelete?.(id);

			if (externalSecrets.length === 0) {
				setLocalSecrets((prev) => prev.filter((secret) => secret.id !== id));
			}

			toast.success("Secret deleted");
		} catch (error) {
			toast.error("Failed to delete secret");
		}
	};

	const handleCopy = (value: string) => {
		navigator.clipboard.writeText(value);
		toast.success("Value copied to clipboard");
	};

	const toggleSecretVisibility = (id: string) => {
		setVisibleSecrets((prev) => {
			const next = new Set(prev);
			if (next.has(id)) {
				next.delete(id);
			} else {
				next.add(id);
			}
			return next;
		});
	};

	const toggleAllVisibility = () => {
		setHideValues(!hideValues);
		if (!hideValues) {
			setVisibleSecrets(new Set());
		}
	};

	const isSecretVisible = (id: string) => {
		return hideValues ? visibleSecrets.has(id) : true;
	};

	return (
		<div className={cn("space-y-4", className)}>
			<Card>
				<CardHeader>
					<div className="flex items-start justify-between">
						<div>
							<CardTitle>Environment Variables</CardTitle>
							<CardDescription>
								Manage your application secrets and configuration
							</CardDescription>
						</div>
						{editable && (
							<Dialog
								open={isCreateDialogOpen}
								onOpenChange={setIsCreateDialogOpen}
							>
								<DialogTrigger asChild>
									<Button>
										<Plus className="mr-2 size-4" />
										Add Secret
									</Button>
								</DialogTrigger>
								<DialogContent>
									<DialogHeader>
										<DialogTitle>Create New Secret</DialogTitle>
									</DialogHeader>
									<SecretForm
										environment={environment}
										environments={environments}
										onSubmit={handleCreate}
										onCancel={() => setIsCreateDialogOpen(false)}
									/>
								</DialogContent>
							</Dialog>
						)}
					</div>
				</CardHeader>
				<CardContent className="space-y-4">
					<div className="flex flex-wrap items-center gap-2">
						<div className="relative flex-1">
							<Search className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
							<Input
								placeholder="Search secrets..."
								value={searchQuery}
								onChange={(e) => setSearchQuery(e.target.value)}
								className="pl-9"
							/>
						</div>
						<Select value={environment} onValueChange={handleEnvironmentChange}>
							<SelectTrigger className="w-[180px]">
								<Filter className="mr-2 size-4" />
								<SelectValue />
							</SelectTrigger>
							<SelectContent>
								<SelectItem value="all">All Environments</SelectItem>
								{environments.map((env) => (
									<SelectItem key={env} value={env}>
										{env.charAt(0).toUpperCase() + env.slice(1)}
									</SelectItem>
								))}
							</SelectContent>
						</Select>
						<Button variant="outline" size="icon" onClick={toggleAllVisibility}>
							{hideValues ? (
								<Eye className="size-4" />
							) : (
								<EyeOff className="size-4" />
							)}
						</Button>
					</div>

					{filteredSecrets.length > 0 ? (
						<div className="rounded-md border">
							<Table>
								<TableHeader>
									<TableRow>
										<TableHead>Key</TableHead>
										<TableHead>Value</TableHead>
										<TableHead>Environment</TableHead>
										<TableHead>Description</TableHead>
										<TableHead className="w-[100px]">Actions</TableHead>
									</TableRow>
								</TableHeader>
								<TableBody>
									{filteredSecrets.map((secret) => (
										<TableRow key={secret.id}>
											<TableCell>
												<code className="rounded bg-muted px-2 py-1 font-mono text-sm">
													{secret.key}
												</code>
											</TableCell>
											<TableCell>
												<div className="flex items-center gap-2">
													<code className="flex-1 rounded bg-muted px-2 py-1 font-mono text-sm">
														{isSecretVisible(secret.id)
															? secret.value
															: "•".repeat(Math.min(secret.value.length, 20))}
													</code>
													<Button
														variant="ghost"
														size="icon-sm"
														onClick={() => toggleSecretVisibility(secret.id)}
													>
														{isSecretVisible(secret.id) ? (
															<EyeOff className="size-4" />
														) : (
															<Eye className="size-4" />
														)}
													</Button>
													<Button
														variant="ghost"
														size="icon-sm"
														onClick={() => handleCopy(secret.value)}
													>
														<Copy className="size-4" />
													</Button>
												</div>
											</TableCell>
											<TableCell>
												<Badge variant="secondary">{secret.environment}</Badge>
											</TableCell>
											<TableCell>
												<span className="text-sm text-muted-foreground">
													{secret.description || "-"}
												</span>
											</TableCell>
											<TableCell>
												{editable && (
													<div className="flex items-center gap-1">
														<Button
															variant="ghost"
															size="icon-sm"
															onClick={() => {
																setEditingSecret(secret);
																setIsEditDialogOpen(true);
															}}
														>
															<Edit className="size-4" />
														</Button>
														<Button
															variant="ghost"
															size="icon-sm"
															onClick={() => handleDelete(secret.id)}
														>
															<Trash2 className="size-4 text-destructive" />
														</Button>
													</div>
												)}
											</TableCell>
										</TableRow>
									))}
								</TableBody>
							</Table>
						</div>
					) : (
						<div className="flex h-32 items-center justify-center rounded-md border-2 border-dashed">
							<p className="text-sm text-muted-foreground">
								{searchQuery
									? "No secrets found matching your search"
									: "No secrets yet. Add your first secret to get started."}
							</p>
						</div>
					)}
				</CardContent>
			</Card>

			{editingSecret && (
				<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
					<DialogContent>
						<DialogHeader>
							<DialogTitle>Edit Secret</DialogTitle>
						</DialogHeader>
						<SecretForm
							secret={editingSecret}
							environment={environment}
							environments={environments}
							onSubmit={(data) => handleUpdate(editingSecret.id, data)}
							onCancel={() => {
								setIsEditDialogOpen(false);
								setEditingSecret(null);
							}}
						/>
					</DialogContent>
				</Dialog>
			)}
		</div>
	);
}
