import { useQuery, useMutation } from "@tanstack/react-query";
import { Database, X, RefreshCw } from "lucide-react";
import { useState } from "react";
import {
	listBackupSchedulesOptions,
	listSnapshotsOptions,
	refreshSnapshotsMutation,
} from "~/client/api-client/@tanstack/react-query.gen";
import { SnapshotsTable } from "~/client/components/snapshots-table";
import { Button } from "~/client/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card";
import { Input } from "~/client/components/ui/input";
import { Table, TableBody, TableCell, TableRow } from "~/client/components/ui/table";
import type { BackupSchedule, Repository, Snapshot } from "~/client/lib/types";
import { toast } from "sonner";

type Props = {
	repository: Repository;
	initialSnapshots?: Snapshot[];
	initialBackupSchedules?: BackupSchedule[];
};

export const RepositorySnapshotsTabContent = ({ repository, initialSnapshots, initialBackupSchedules }: Props) => {
	const [searchQuery, setSearchQuery] = useState("");

	const { data, isPending, failureReason } = useQuery({
		...listSnapshotsOptions({ path: { shortId: repository.shortId } }),
		initialData: initialSnapshots,
	});

	const schedules = useQuery({
		...listBackupSchedulesOptions(),
		initialData: initialBackupSchedules,
	});

	const refreshMutation = useMutation({
		...refreshSnapshotsMutation(),
		onSuccess: (data) => {
			toast.success(`Snapshot cache refreshed. Found ${data.count} snapshots.`);
		},
		onError: (error) => {
			toast.error(`Failed to refresh snapshots: ${error.message}`);
		},
	});

	const handleRefresh = () => {
		refreshMutation.mutate({ path: { shortId: repository.shortId } });
	};

	const snapshots = data ?? [];

	const filteredSnapshots = snapshots.filter((snapshot: Snapshot) => {
		if (!searchQuery) return true;
		const searchLower = searchQuery.toLowerCase();

		const backup = schedules.data?.find((b) => snapshot.tags.includes(b.shortId));

		return (
			snapshot.short_id.toLowerCase().includes(searchLower) ||
			snapshot.paths.some((path) => path.toLowerCase().includes(searchLower)) ||
			backup?.name?.toLowerCase().includes(searchLower) ||
			backup?.volume?.name?.toLowerCase().includes(searchLower)
		);
	});

	const hasNoFilteredSnapshots = !filteredSnapshots.length;

	if (repository.status === "error") {
		return (
			<Card>
				<CardContent className="flex flex-col items-center justify-center text-center py-12">
					<Database className="mb-4 h-12 w-12 text-destructive" />
					<p className="text-destructive font-semibold">Repository error</p>
					<p className="text-sm text-muted-foreground mt-2">
						This repository is in an error state and cannot be accessed.
					</p>
					{repository.lastError && (
						<div className="mt-4 w-full max-w-md bg-destructive/10 border border-destructive/20 rounded-md p-3">
							<p className="text-sm text-destructive wrap-break-word">{repository.lastError}</p>
						</div>
					)}
				</CardContent>
			</Card>
		);
	}

	if (failureReason) {
		return (
			<Card>
				<CardContent className="flex flex-col items-center justify-center text-center py-12">
					<Database className="mb-4 h-12 w-12 text-destructive" />
					<p className="text-destructive font-semibold">Failed to Load Snapshots</p>
					<p className="text-sm text-muted-foreground mt-2">{failureReason.message}</p>
				</CardContent>
			</Card>
		);
	}

	if (isPending) {
		return (
			<Card>
				<CardContent className="flex items-center justify-center py-12">
					<p className="text-muted-foreground">Loading snapshots</p>
				</CardContent>
			</Card>
		);
	}

	if (!snapshots.length) {
		return (
			<Card>
				<CardContent className="flex flex-col items-center justify-center text-center py-16 px-4">
					<div className="relative mb-8">
						<div className="absolute inset-0 animate-pulse">
							<div className="w-32 h-32 rounded-full bg-primary/10 blur-2xl" />
						</div>
						<div className="relative flex items-center justify-center w-32 h-32 rounded-full bg-linear-to-br from-primary/20 to-primary/5 border-2 border-primary/20">
							<Database className="w-16 h-16 text-primary/70" strokeWidth={1.5} />
						</div>
					</div>
					<div className="max-w-md space-y-3">
						<h3 className="text-2xl font-semibold text-foreground">No snapshots yet</h3>
						<p className="text-muted-foreground text-sm">
							Snapshots are point-in-time backups of your data. Create your first backup to see it here.
						</p>
					</div>
				</CardContent>
			</Card>
		);
	}

	return (
		<Card className="p-0 gap-0">
			<CardHeader className="p-4 bg-card-header">
				<div className="flex flex-col lg:flex-row items-stretch lg:items-center gap-4 justify-between">
					<div className="flex-1">
						<CardTitle>Snapshots</CardTitle>
						<CardDescription className="mt-1">
							Backup snapshots stored in this repository. Total: {snapshots.length}
						</CardDescription>
					</div>
					<div className="flex gap-2 items-center">
						<Input
							className="w-full lg:w-60"
							placeholder="Search snapshots..."
							value={searchQuery}
							onChange={(e) => setSearchQuery(e.target.value)}
						/>
						<Button
							onClick={handleRefresh}
							variant="outline"
							disabled={refreshMutation.isPending}
							title="Refresh snapshot list"
						>
							<RefreshCw className={refreshMutation.isPending ? "h-4 w-4 animate-spin" : "h-4 w-4"} />
						</Button>
					</div>
				</div>
			</CardHeader>
			{hasNoFilteredSnapshots ? (
				<Table className="border-t">
					<TableBody>
						<TableRow>
							<TableCell colSpan={5} className="text-center py-12">
								<div className="flex flex-col items-center gap-3">
									<p className="text-muted-foreground">No snapshots match your search.</p>
									<Button onClick={() => setSearchQuery("")} variant="outline" size="sm">
										<X className="h-4 w-4 mr-2" />
										Clear search
									</Button>
								</div>
							</TableCell>
						</TableRow>
					</TableBody>
				</Table>
			) : (
				<SnapshotsTable
					snapshots={filteredSnapshots}
					repositoryId={repository.shortId}
					backups={schedules.data ?? []}
					listSnapshotsQueryOptions={{ path: { shortId: repository.shortId } }}
				/>
			)}
			<div className="px-4 py-2 text-sm text-muted-foreground bg-card-header flex justify-between border-t">
				<span>
					{hasNoFilteredSnapshots
						? "No snapshots match filters."
						: `Showing ${filteredSnapshots.length} of ${snapshots.length}`}
				</span>
			</div>
		</Card>
	);
};
