"use client";

import {
	closestCenter,
	DndContext,
	type DragEndEvent,
	KeyboardSensor,
	PointerSensor,
	useSensor,
	useSensors,
} from "@dnd-kit/core";
import {
	arrayMove,
	SortableContext,
	useSortable,
	verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { RiDragMove2Line } from "@remixicon/react";
import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";
import { toast } from "sonner";
import { updatePreferencesAction } from "@/features/settings/actions";
import {
	DEFAULT_LANCAMENTOS_COLUMN_ORDER,
	LANCAMENTOS_COLUMN_LABELS,
} from "@/features/transactions/column-order";
import { Button } from "@/shared/components/ui/button";
import { Label } from "@/shared/components/ui/label";
import { Switch } from "@/shared/components/ui/switch";

interface PreferencesFormProps {
	extratoNoteAsColumn: boolean;
	lancamentosColumnOrder: string[] | null;
}

function SortableColumnItem({ id }: { id: string }) {
	const {
		attributes,
		listeners,
		setNodeRef,
		transform,
		transition,
		isDragging,
	} = useSortable({ id });

	const style = {
		transform: CSS.Transform.toString(transform),
		transition,
	};

	const label = LANCAMENTOS_COLUMN_LABELS[id] ?? id;

	return (
		<div
			ref={setNodeRef}
			style={style}
			className={`flex cursor-grab active:cursor-grabbing items-center gap-2 rounded-md border bg-card px-3 py-2 text-sm touch-none select-none ${
				isDragging ? "z-10 opacity-90 shadow-md" : ""
			}`}
			aria-label={`Arrastar ${label}`}
			{...attributes}
			{...listeners}
		>
			<RiDragMove2Line
				className="size-4 shrink-0 text-muted-foreground"
				aria-hidden
			/>
			<span>{label}</span>
		</div>
	);
}

export function PreferencesForm({
	extratoNoteAsColumn: initialExtratoNoteAsColumn,
	lancamentosColumnOrder: initialColumnOrder,
}: PreferencesFormProps) {
	const router = useRouter();
	const [isPending, startTransition] = useTransition();
	const [extratoNoteAsColumn, setExtratoNoteAsColumn] = useState(
		initialExtratoNoteAsColumn,
	);
	const [columnOrder, setColumnOrder] = useState<string[]>(
		initialColumnOrder && initialColumnOrder.length > 0
			? initialColumnOrder
			: DEFAULT_LANCAMENTOS_COLUMN_ORDER,
	);

	const sensors = useSensors(
		useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
		useSensor(KeyboardSensor),
	);

	const handleColumnDragEnd = (event: DragEndEvent) => {
		const { active, over } = event;
		if (over && active.id !== over.id) {
			setColumnOrder((items) => {
				const oldIndex = items.indexOf(active.id as string);
				const newIndex = items.indexOf(over.id as string);
				return arrayMove(items, oldIndex, newIndex);
			});
		}
	};

	const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
		event.preventDefault();

		startTransition(async () => {
			const result = await updatePreferencesAction({
				extratoNoteAsColumn,
				lancamentosColumnOrder: columnOrder,
			});

			if (result.success) {
				toast.success(result.message);
				router.refresh();
			} else {
				toast.error(result.error);
			}
		});
	};

	return (
		<form onSubmit={handleSubmit} className="flex flex-col gap-8">
			{/* Seção: Extrato / Lançamentos */}
			<section className="space-y-4">
				<div>
					<h3 className="text-base font-semibold">Extrato e lançamentos</h3>
					<p className="text-sm text-muted-foreground">
						Como exibir anotações e a ordem das colunas na tabela de
						movimentações.
					</p>
				</div>

				<div className="flex items-center justify-between rounded-lg border p-4 max-w-md">
					<div className="space-y-0.5">
						<Label htmlFor="extrato-note-column" className="text-base">
							Anotações em coluna
						</Label>
						<p className="text-sm text-muted-foreground">
							Quando ativo, as anotações aparecem em uma coluna na tabela.
							Quando desativado, aparecem em um balão ao passar o mouse no
							ícone.
						</p>
					</div>
					<Switch
						id="extrato-note-column"
						checked={extratoNoteAsColumn}
						onCheckedChange={setExtratoNoteAsColumn}
						disabled={isPending}
					/>
				</div>

				<div className="space-y-2 max-w-md">
					<Label className="text-base">Ordem das colunas</Label>
					<p className="text-sm text-muted-foreground">
						Arraste os itens para definir a ordem em que as colunas aparecem na
						tabela do extrato e dos lançamentos.
					</p>
					<DndContext
						sensors={sensors}
						collisionDetection={closestCenter}
						onDragEnd={handleColumnDragEnd}
					>
						<SortableContext
							items={columnOrder}
							strategy={verticalListSortingStrategy}
						>
							<div className="flex flex-col gap-2 pt-2">
								{columnOrder.map((id) => (
									<SortableColumnItem key={id} id={id} />
								))}
							</div>
						</SortableContext>
					</DndContext>
				</div>
			</section>

			<div className="flex justify-end">
				<Button type="submit" disabled={isPending} className="w-fit">
					{isPending ? "Salvando..." : "Salvar preferências"}
				</Button>
			</div>
		</form>
	);
}
