import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table";
import axios from "axios";
import { ArrowDown, ArrowUp } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { getSettings } from "@/lib/querys/admin/getSettings";
import TableNoExpand from "@/lib/tableStuff/TableNoExpand";

type Settings = {
	settings_id: string;
	name: string;
	active: boolean;
	value: string;
	description: string;
	moduleName: string;
	roles: string[];
};

const updateSettings = async (
	id: string,
	data: Record<string, string | number | boolean | null>,
) => {
	console.log(id, data);
	try {
		const res = await axios.patch(`/lst/api/system/settings/${id}`, data, {
			withCredentials: true,
		});
		toast.success(`Setting just updated`);
		return res;
	} catch (err) {
		toast.error("Error in updating the settings");
		return err;
	}
};

export const Route = createFileRoute(
	"/_app/_adminLayout/admin/_system/settings",
)({
	component: RouteComponent,
});

function RouteComponent() {
	const { data, isLoading, refetch } = useQuery(getSettings());
	const columnHelper = createColumnHelper<Settings>();
	const submitting = useRef(false);

	const updateSetting = useMutation({
		mutationFn: ({
			id,
			field,
			value,
		}: {
			id: string;
			field: string;
			value: string | number | boolean | null;
		}) => updateSettings(id, { [field]: value }),

		onSuccess: () => {
			// refetch or update cache
			refetch();
		},
	});

	const columns = [
		columnHelper.accessor("name", {
			header: ({ column }) => {
				return (
					<Button
						variant="ghost"
						onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
					>
						<span className="flex flex-row gap-2">Name</span>
						{column.getIsSorted() === "asc" ? (
							<ArrowUp className="ml-2 h-4 w-4" />
						) : (
							<ArrowDown className="ml-2 h-4 w-4" />
						)}
					</Button>
				);
			},
			cell: (i) => i.getValue(),
		}),
		columnHelper.accessor("description", {
			header: ({ column }) => {
				return (
					<Button
						variant="ghost"
						onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
					>
						<span className="flex flex-row gap-2">Description</span>
						{column.getIsSorted() === "asc" ? (
							<ArrowUp className="ml-2 h-4 w-4" />
						) : (
							<ArrowDown className="ml-2 h-4 w-4" />
						)}
					</Button>
				);
			},
			cell: (i) => i.getValue(),
		}),
		columnHelper.accessor("value", {
			header: ({ column }) => {
				return (
					<Button
						variant="ghost"
						onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
					>
						<span className="flex flex-row gap-2">Value</span>
						{column.getIsSorted() === "asc" ? (
							<ArrowUp className="ml-2 h-4 w-4" />
						) : (
							<ArrowDown className="ml-2 h-4 w-4" />
						)}
					</Button>
				);
			},
			cell: ({ row, getValue }) => {
				const initialValue = String(getValue() ?? "");
				const [localValue, setLocalValue] = useState(initialValue);

				const id = row.original.settings_id;
				const field = "value";

				useEffect(() => setLocalValue(initialValue), [initialValue]);

				const handleSubmit = (newValue: string) => {
					if (newValue !== initialValue) {
						setLocalValue(newValue);
						updateSetting.mutate({ id, field, value: newValue });
					}
				};

				return (
					<Input
						value={localValue}
						onChange={(e) => setLocalValue(e.currentTarget.value)}
						onBlur={(e) => {
							if (!submitting.current) {
								submitting.current = true;
								handleSubmit(e.currentTarget.value.trim());
								setTimeout(() => (submitting.current = false), 100); // reset after slight delay
							}
						}}
						onKeyDown={(e) => {
							if (e.key === "Enter") {
								e.preventDefault();
								submitting.current = true;
								handleSubmit(e.currentTarget.value.trim());
								e.currentTarget.blur(); // will trigger blur, but we ignore it
								setTimeout(() => (submitting.current = false), 100);
							}
						}}
					/>
				);
			},
		}),
		columnHelper.accessor("moduleName", {
			header: ({ column }) => {
				return (
					<Button
						variant="ghost"
						onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
					>
						<span className="flex flex-row gap-2">Module Name</span>
						{column.getIsSorted() === "asc" ? (
							<ArrowUp className="ml-2 h-4 w-4" />
						) : (
							<ArrowDown className="ml-2 h-4 w-4" />
						)}
					</Button>
				);
			},
			cell: ({ row, getValue }) => {
				const initialValue = String(getValue() ?? "");
				const [localValue, setLocalValue] = useState(initialValue);

				const id = row.original.settings_id;
				const field = "moduleName";

				useEffect(() => setLocalValue(initialValue), [initialValue]);

				const handleSubmit = (newValue: string) => {
					if (newValue !== initialValue) {
						setLocalValue(newValue);
						updateSetting.mutate({ id, field, value: newValue });
					}
				};

				return (
					<Input
						value={localValue}
						onChange={(e) => setLocalValue(e.currentTarget.value)}
						onBlur={(e) => {
							if (!submitting.current) {
								submitting.current = true;
								handleSubmit(e.currentTarget.value.trim());
								setTimeout(() => (submitting.current = false), 100); // reset after slight delay
							}
						}}
						onKeyDown={(e) => {
							if (e.key === "Enter") {
								e.preventDefault();
								submitting.current = true;
								handleSubmit(e.currentTarget.value.trim());
								e.currentTarget.blur(); // will trigger blur, but we ignore it
								setTimeout(() => (submitting.current = false), 100);
							}
						}}
					/>
				);
			},
		}),
	];

	if (isLoading)
		return (
			<div>
				<span>Loading settings data</span>
			</div>
		);
	return (
		<div className="m-2">
			<TableNoExpand data={data} columns={columns} />
		</div>
	);
}
