import {
	faChevronLeft,
	faFile,
	faFileImport,
	faLayerGroup,
	faPen,
	faPlus,
	faTrash,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useAtomValue, useSetAtom } from "jotai";
import { Suspense, useMemo, useState, useTransition } from "react";
import { Link, useParams } from "wouter";
import { type Card, cardsByDeckAtomFamily, deckByIdAtomFamily } from "../atoms";
import { CreateNoteModal } from "../components/CreateNoteModal";
import { DeleteCardModal } from "../components/DeleteCardModal";
import { DeleteNoteModal } from "../components/DeleteNoteModal";
import { EditCardModal } from "../components/EditCardModal";
import { EditNoteModal } from "../components/EditNoteModal";
import { ErrorBoundary } from "../components/ErrorBoundary";
import { ImportNotesModal } from "../components/ImportNotesModal";
import { LoadingSpinner } from "../components/LoadingSpinner";

/** Combined type for display: note group */
type CardDisplayItem = { type: "note"; noteId: string; cards: Card[] };

const CardStateLabels: Record<number, string> = {
	0: "New",
	1: "Learning",
	2: "Review",
	3: "Relearning",
};

const CardStateColors: Record<number, string> = {
	0: "bg-info/10 text-info",
	1: "bg-warning/10 text-warning",
	2: "bg-success/10 text-success",
	3: "bg-error/10 text-error",
};

/** Component for displaying a group of cards from the same note */
function NoteGroupCard({
	noteId,
	cards,
	index,
	onEditNote,
	onDeleteNote,
}: {
	noteId: string;
	cards: Card[];
	index: number;
	onEditNote: () => void;
	onDeleteNote: () => void;
}) {
	// Use the first card's front/back as preview (normal card takes precedence)
	const previewCard = cards.find((c) => !c.isReversed) ?? cards[0];
	if (!previewCard) return null;

	return (
		<div
			data-testid="note-group"
			data-note-id={noteId}
			className="bg-white rounded-xl border border-border/50 shadow-card hover:shadow-md transition-all duration-200 overflow-hidden"
			style={{ animationDelay: `${index * 30}ms` }}
		>
			{/* Note Header */}
			<div className="flex items-center justify-between px-5 py-3 border-b border-border/30 bg-ivory/30">
				<div className="flex items-center gap-2">
					<FontAwesomeIcon
						icon={faLayerGroup}
						className="w-4 h-4 text-muted"
						aria-hidden="true"
					/>
					<span className="text-sm font-medium text-slate">
						Note ({cards.length} card{cards.length !== 1 ? "s" : ""})
					</span>
				</div>
				<div className="flex items-center gap-1">
					<button
						type="button"
						onClick={onEditNote}
						className="p-2 text-muted hover:text-slate hover:bg-white rounded-lg transition-colors"
						title="Edit note"
					>
						<FontAwesomeIcon
							icon={faPen}
							className="w-4 h-4"
							aria-hidden="true"
						/>
					</button>
					<button
						type="button"
						onClick={onDeleteNote}
						className="p-2 text-muted hover:text-error hover:bg-error/5 rounded-lg transition-colors"
						title="Delete note"
					>
						<FontAwesomeIcon
							icon={faTrash}
							className="w-4 h-4"
							aria-hidden="true"
						/>
					</button>
				</div>
			</div>

			{/* Note Content Preview */}
			<div className="p-5">
				<div className="grid grid-cols-2 gap-4 mb-4">
					<div>
						<span className="text-xs font-medium text-muted uppercase tracking-wide">
							Front
						</span>
						<p className="mt-1 text-slate text-sm line-clamp-2 whitespace-pre-wrap break-words">
							{previewCard.front}
						</p>
					</div>
					<div>
						<span className="text-xs font-medium text-muted uppercase tracking-wide">
							Back
						</span>
						<p className="mt-1 text-slate text-sm line-clamp-2 whitespace-pre-wrap break-words">
							{previewCard.back}
						</p>
					</div>
				</div>

				{/* Cards within this note */}
				<div className="space-y-2">
					{cards.map((card) => (
						<div
							key={card.id}
							data-testid="note-card"
							className="flex items-center gap-3 text-xs p-2 bg-ivory/50 rounded-lg"
						>
							<span
								className={`px-2 py-0.5 rounded-full font-medium ${CardStateColors[card.state] || "bg-muted/10 text-muted"}`}
							>
								{CardStateLabels[card.state] || "Unknown"}
							</span>
							{card.isReversed ? (
								<span className="px-2 py-0.5 rounded-full font-medium bg-purple-100 text-purple-700">
									Reversed
								</span>
							) : (
								<span className="px-2 py-0.5 rounded-full font-medium bg-blue-100 text-blue-700">
									Normal
								</span>
							)}
							<span className="text-muted">{card.reps} reviews</span>
							{card.lapses > 0 && (
								<span className="text-muted">{card.lapses} lapses</span>
							)}
						</div>
					))}
				</div>
			</div>
		</div>
	);
}

function DeckHeader({ deckId }: { deckId: string }) {
	const deck = useAtomValue(deckByIdAtomFamily(deckId));

	return (
		<div className="mb-8">
			<h1 className="font-display text-3xl font-semibold text-ink mb-2">
				{deck.name}
			</h1>
			{deck.description && <p className="text-muted">{deck.description}</p>}
		</div>
	);
}

function CardList({
	deckId,
	onEditNote,
	onDeleteNote,
	onCreateNote,
}: {
	deckId: string;
	onEditNote: (noteId: string) => void;
	onDeleteNote: (noteId: string) => void;
	onCreateNote: () => void;
}) {
	const cards = useAtomValue(cardsByDeckAtomFamily(deckId));

	// Group cards by note for display
	const displayItems = useMemo((): CardDisplayItem[] => {
		const noteGroups = new Map<string, Card[]>();

		for (const card of cards) {
			const existing = noteGroups.get(card.noteId);
			if (existing) {
				existing.push(card);
			} else {
				noteGroups.set(card.noteId, [card]);
			}
		}

		// Sort note groups by earliest card creation (newest first)
		const sortedNoteGroups = Array.from(noteGroups.entries()).sort(
			([, cardsA], [, cardsB]) => {
				const minA = Math.min(
					...cardsA.map((c) => new Date(c.createdAt).getTime()),
				);
				const minB = Math.min(
					...cardsB.map((c) => new Date(c.createdAt).getTime()),
				);
				return minB - minA; // Newest first
			},
		);

		const items: CardDisplayItem[] = [];
		for (const [noteId, noteCards] of sortedNoteGroups) {
			// Sort cards within group: normal first, then reversed
			noteCards.sort((a, b) => {
				if (a.isReversed === b.isReversed) return 0;
				return a.isReversed ? 1 : -1;
			});
			items.push({ type: "note", noteId, cards: noteCards });
		}

		return items;
	}, [cards]);

	if (cards.length === 0) {
		return (
			<div className="text-center py-12 bg-white rounded-xl border border-border/50">
				<div className="w-14 h-14 mx-auto mb-4 bg-ivory rounded-xl flex items-center justify-center">
					<FontAwesomeIcon
						icon={faFile}
						className="w-7 h-7 text-muted"
						aria-hidden="true"
					/>
				</div>
				<h3 className="font-display text-lg font-medium text-slate mb-2">
					No cards yet
				</h3>
				<p className="text-muted text-sm mb-4">Add notes to start studying</p>
				<button
					type="button"
					onClick={onCreateNote}
					className="inline-flex items-center gap-2 bg-primary hover:bg-primary-dark text-white font-medium py-2 px-4 rounded-lg transition-all duration-200"
				>
					<FontAwesomeIcon
						icon={faPlus}
						className="w-5 h-5"
						aria-hidden="true"
					/>
					Add Your First Note
				</button>
			</div>
		);
	}

	return (
		<div className="space-y-4">
			{displayItems.map((item, index) => (
				<NoteGroupCard
					key={item.noteId}
					noteId={item.noteId}
					cards={item.cards}
					index={index}
					onEditNote={() => onEditNote(item.noteId)}
					onDeleteNote={() => onDeleteNote(item.noteId)}
				/>
			))}
		</div>
	);
}

function CardsContent({
	deckId,
	onCreateNote,
	onImportNotes,
	onEditNote,
	onDeleteNote,
}: {
	deckId: string;
	onCreateNote: () => void;
	onImportNotes: () => void;
	onEditNote: (noteId: string) => void;
	onDeleteNote: (noteId: string) => void;
}) {
	const cards = useAtomValue(cardsByDeckAtomFamily(deckId));

	return (
		<div className="animate-fade-in">
			{/* Deck Header */}
			<ErrorBoundary>
				<Suspense fallback={<LoadingSpinner />}>
					<DeckHeader deckId={deckId} />
				</Suspense>
			</ErrorBoundary>

			{/* Cards Section */}
			<div className="flex items-center justify-between mb-6">
				<h2 className="font-display text-xl font-medium text-slate">
					Cards <span className="text-muted font-normal">({cards.length})</span>
				</h2>
				<div className="flex items-center gap-2">
					<button
						type="button"
						onClick={onImportNotes}
						className="inline-flex items-center gap-2 border border-border hover:bg-ivory text-slate font-medium py-2 px-4 rounded-lg transition-all duration-200 active:scale-[0.98]"
					>
						<FontAwesomeIcon
							icon={faFileImport}
							className="w-5 h-5"
							aria-hidden="true"
						/>
						Import CSV
					</button>
					<button
						type="button"
						onClick={onCreateNote}
						className="inline-flex items-center gap-2 bg-primary hover:bg-primary-dark text-white font-medium py-2 px-4 rounded-lg transition-all duration-200 active:scale-[0.98]"
					>
						<FontAwesomeIcon
							icon={faPlus}
							className="w-5 h-5"
							aria-hidden="true"
						/>
						Add Note
					</button>
				</div>
			</div>

			{/* Card List */}
			<CardList
				deckId={deckId}
				onEditNote={onEditNote}
				onDeleteNote={onDeleteNote}
				onCreateNote={onCreateNote}
			/>
		</div>
	);
}

export function DeckCardsPage() {
	const { deckId } = useParams<{ deckId: string }>();
	const [, startTransition] = useTransition();

	const reloadCards = useSetAtom(cardsByDeckAtomFamily(deckId || ""));

	const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
	const [isImportModalOpen, setIsImportModalOpen] = useState(false);
	const [editingCard, setEditingCard] = useState<Card | null>(null);
	const [editingNoteId, setEditingNoteId] = useState<string | null>(null);
	const [deletingCard, setDeletingCard] = useState<Card | null>(null);
	const [deletingNoteId, setDeletingNoteId] = useState<string | null>(null);

	const handleCardMutation = () => {
		startTransition(() => {
			reloadCards();
		});
	};

	if (!deckId) {
		return (
			<div className="min-h-screen bg-cream flex items-center justify-center">
				<div className="text-center">
					<p className="text-muted mb-4">Invalid deck ID</p>
					<Link
						href="/"
						className="text-primary hover:text-primary-dark font-medium"
					>
						Back to decks
					</Link>
				</div>
			</div>
		);
	}

	return (
		<div className="min-h-screen bg-cream">
			{/* Header */}
			<header className="bg-white border-b border-border/50">
				<div className="max-w-4xl mx-auto px-4 py-4">
					<Link
						href={`/decks/${deckId}`}
						className="inline-flex items-center gap-2 text-muted hover:text-slate transition-colors text-sm"
					>
						<FontAwesomeIcon
							icon={faChevronLeft}
							className="w-4 h-4"
							aria-hidden="true"
						/>
						Back to Deck
					</Link>
				</div>
			</header>

			{/* Main Content */}
			<main className="max-w-4xl mx-auto px-4 py-8">
				<ErrorBoundary>
					<Suspense fallback={<LoadingSpinner />}>
						<CardsContent
							deckId={deckId}
							onCreateNote={() => setIsCreateModalOpen(true)}
							onImportNotes={() => setIsImportModalOpen(true)}
							onEditNote={setEditingNoteId}
							onDeleteNote={setDeletingNoteId}
						/>
					</Suspense>
				</ErrorBoundary>
			</main>

			{/* Modals */}
			<CreateNoteModal
				isOpen={isCreateModalOpen}
				deckId={deckId}
				onClose={() => setIsCreateModalOpen(false)}
				onNoteCreated={handleCardMutation}
			/>

			<ImportNotesModal
				isOpen={isImportModalOpen}
				deckId={deckId}
				onClose={() => setIsImportModalOpen(false)}
				onImportComplete={handleCardMutation}
			/>

			<EditCardModal
				isOpen={editingCard !== null}
				deckId={deckId}
				card={editingCard}
				onClose={() => setEditingCard(null)}
				onCardUpdated={handleCardMutation}
			/>

			<EditNoteModal
				isOpen={editingNoteId !== null}
				deckId={deckId}
				noteId={editingNoteId}
				onClose={() => setEditingNoteId(null)}
				onNoteUpdated={handleCardMutation}
			/>

			<DeleteCardModal
				isOpen={deletingCard !== null}
				deckId={deckId}
				card={deletingCard}
				onClose={() => setDeletingCard(null)}
				onCardDeleted={handleCardMutation}
			/>

			<DeleteNoteModal
				isOpen={deletingNoteId !== null}
				deckId={deckId}
				noteId={deletingNoteId}
				onClose={() => setDeletingNoteId(null)}
				onNoteDeleted={handleCardMutation}
			/>
		</div>
	);
}
