import { queryClient } from '@/woocommerce/elements/data-field/query-client';
import { WooCommerceOrder } from '@/woocommerce/types/woocommerce';
import { useDebounceCallback } from '@pdfdraft/core/hooks/use-debounce-callback';
import { useDebounceValue } from '@pdfdraft/core/hooks/use-debounce-value';
import { useDisclosure } from '@pdfdraft/core/hooks/use-disclosure';
import { Button } from '@pdfdraft/ui/components/button';
import {
	Command,
	CommandEmpty,
	CommandGroup,
	CommandInput,
	CommandItem,
	CommandList,
	CommandLoading,
} from '@pdfdraft/ui/components/command';
import {
	Popover,
	PopoverContent,
	PopoverTrigger,
} from '@pdfdraft/ui/components/popover';
import { ScrollAreaPrimitive } from '@pdfdraft/ui/components/scroll-area';
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from '@pdfdraft/ui/components/select';
import { Separator } from '@pdfdraft/ui/components/separator';
import { Skeleton } from '@pdfdraft/ui/components/skeleton';
import { ChevronDown, LoaderCircle, RotateCw } from '@pdfdraft/ui/icons';
import {
	QueryClientProvider,
	useInfiniteQuery,
	useMutation,
	useQuery,
} from '@tanstack/react-query';
import apiFetch from '@wordpress/api-fetch';
import { __, sprintf } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';
import { format } from 'date-fns';
import { memo, useEffect, useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useEditorStore } from '@pdfdraft/core/stores/editor.store';

function getPageFromUrl(url: string) {
	const match = url.match(/[?&]page=(\d+)/);
	return match?.[1] ? parseInt(match[1], 10) : undefined;
}

function getPageInfo(linkHeader: string) {
	const links = linkHeader
		.split(', ')
		.reduce<Record<string, number | undefined>>(
			(acc, link) => {
				const [url, rel] = link.split('; ') as [string, string];
				const cleanUrl = url.slice(1, -1);
				const page = getPageFromUrl(cleanUrl);
				if (rel.includes('prev')) acc.prev = page;
				if (rel.includes('next')) acc.next = page;
				return acc;
			},
			{ prev: undefined, next: undefined },
		);
	const currentPage = links.prev ? links.prev + 1 : 1;
	return {
		current: currentPage,
		next: links.next,
		prev: links.prev,
	};
}

const SettingsInner = memo(() => {
	const selectedElementId = useEditorStore(
		(state) => state.selectedElementIds.at(0),
	);

	const normalizeType = (t?: string | null) =>
		String(t ?? '')
			.trim()
			.toLowerCase()
			.replace(/_/g, '-');

	const isWooSelected = useMemo(() => {
		if (!selectedElementId) return false;
		const el = useEditorStore.getState().actions.getElementById(selectedElementId);
		return normalizeType(el?.type) === 'woocommerce';
	}, [selectedElementId]);

	const form = useForm({
		defaultValues: {
			woocommerce_data_source: {
				type: 'dummy_data',
				order_id: 0,
			},
		},
	});
	const { isLoading, isError, data, isSuccess } = useQuery({
		queryKey: ['settings'],
		queryFn: async () => {
			const response = await apiFetch<{
				_pdfdraft_settings: Record<string, any> & {
					woocommerce_data_source: {
						type: string;
						order_id: number;
					};
				};
			}>({
				path: 'pdfdraft/v1/settings',
			});
			if (response._pdfdraft_settings.woocommerce_data_source) {
				form.reset({
					woocommerce_data_source:
						response._pdfdraft_settings.woocommerce_data_source,
				});
			}
			return response;
		},
		enabled: isWooSelected,
	});

	const watchSourceType = form.watch('woocommerce_data_source.type');
	const watchOrderId = form.watch('woocommerce_data_source.order_id');
	const [orderFilters, setOrderFilters] = useState({
		offset: 0,
		search: '',
	});
	const orderQuery = useQuery({
		queryKey: ['order'],
		queryFn: async () => {
			return apiFetch<WooCommerceOrder>({
				path: `/wc/v3/orders/${watchOrderId}`,
			});
		},
		enabled: isWooSelected && !!watchOrderId,
	});
	const [searchTerm, setSearchTerm] = useDebounceValue(
		orderFilters.search,
		400,
	);

	const ordersQuery = useInfiniteQuery({
		queryKey: [
			'orders',
			{
				offset: orderFilters.offset,
				search: searchTerm,
			},
		],
		queryFn: async ({ queryKey }) => {
			const args = queryKey.at(1)! as Object;

			const response = await apiFetch<Response, false>({
				path: addQueryArgs('/wc/v3/orders', {
					per_page: 20,
					...args,
				}),
				parse: false,
			});
			if (!(response.status >= 200 && response.status < 300)) throw response;

			let data = (await response.json()) as WooCommerceOrder[];
			const total = response.headers.get('X-WP-Total');
			const pages = response.headers.get('X-WP-TotalPages');
			const linkHeader = response.headers.get('link') ?? '';
			const pageInfo = getPageInfo(linkHeader);
			const counts = response.headers.get('X-WP-Counts');
			return {
				data,
				total: total ? Number(total) : 0,
				pages: pages ? Number(pages) : 0,
				counts: (counts ? JSON.parse(counts) : {}) as Record<
					string,
					string | number
				>,
				...pageInfo,
			};
		},
		enabled:
			isWooSelected &&
			(watchSourceType === 'chosen_order_data' ||
				watchSourceType === 'latest_order_data'),
		initialPageParam: 0,
		getNextPageParam: (lastPage, page) => {
			return lastPage.next;
		},
		staleTime: Infinity,
		gcTime: Infinity,
	});

	const { isOpen, onOpen, onToggle, onClose } = useDisclosure();

	const orders =
		ordersQuery?.data?.pages?.flat()?.reduce((acc, curr) => {
			acc = [...acc, ...curr.data];
			return acc;
		}, [] as WooCommerceOrder[]) ?? [];

	useEffect(() => {
		if (orderQuery.data && orderQuery.isSuccess) {
			window._PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_ORDER_DATA_ = orderQuery.data;
		}
	}, [orderQuery.data, orderQuery.isSuccess]);

	// For "latest order" mode, also expose the fetched latest order data
	// (so Product Table preview/PDF snapshots can show real quantities).
	useEffect(() => {
		if (!isWooSelected) return;
		if (watchSourceType !== 'latest_order_data') return;
		if (orders.length) {
			window._PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_ORDER_DATA_ = orders[0]!;
		}
	}, [isWooSelected, watchSourceType, orders]);

	useEffect(() => {
		if (isSuccess && data) {
			form.reset({
				woocommerce_data_source:
					data._pdfdraft_settings.woocommerce_data_source,
			});
		}
	}, [isSuccess, data]);

	const settingsMutation = useMutation({
		mutationFn: async () => {
			return apiFetch<{
				_pdfdraft_settings: Record<string, any> & {
					woocommerce_data_source: {
						type: string;
						order_id: number;
					};
				};
			}>({
				path: 'pdfdraft/v1/settings',
				method: 'post',
				data: {
					_pdfdraft_settings: {
						...(data?._pdfdraft_settings ?? {}),
						woocommerce_data_source: form.getValues('woocommerce_data_source'),
					},
				},
			});
		},
		onSuccess(data) {
			queryClient.setQueryData(['settings'], () => data);
		},
	});

	const debouncedSettingsMutation = useDebounceCallback(
		settingsMutation.mutate,
		400,
	);

	if (!isWooSelected) return null;

	if (isLoading) {
		return (
			<div className="p-4 pt-0">
				<Separator className="my-5" />
				<Skeleton className="h-[24px] w-[84px]" />
				<Skeleton className="mb-5 mt-1 h-[38px] w-full"></Skeleton>
				<Skeleton className="h-[38px] w-full"></Skeleton>
			</div>
		);
	}

	return (
		<div className="p-4 pt-0">
			<Separator className="my-5" />
			<form onChange={() => debouncedSettingsMutation()} className="space-y-2">
				<Controller
					control={form.control}
					name="woocommerce_data_source.type"
					render={({ field }) => (
						<div className="space-y-2">
							<label
								htmlFor="PDFDraft-Woocommerce-Data-Source-Type"
								className="mb-1 flex items-center gap-2 text-sm font-medium leading-[24px] text-[#383838]"
							>
								<span>{__('Select Order', 'pdfdraft-pdf-invoices-for-woocommerce')}</span>
								{settingsMutation.isPending && (
									<RotateCw className="animate-spin text-gray-400" size={14} />
								)}
							</label>
							<Select
								value={field.value}
								onValueChange={(v) => field.onChange(v)}
							>
								<SelectTrigger
									id="PDFDraft-Woocommerce-Data-Source-Type"
									className="focus:ring-primary h-[38px] w-full rounded py-0 text-sm shadow-none"
								>
									<SelectValue />
								</SelectTrigger>
								<SelectContent className="shadow-none">
									<SelectItem className="text-sm capitalize" value="dummy_data">
										{__('Dummy order data', 'pdfdraft-pdf-invoices-for-woocommerce')}
									</SelectItem>
									<SelectItem
										className="text-sm capitalize"
										value="latest_order_data"
									>
										{__('Latest order', 'pdfdraft-pdf-invoices-for-woocommerce')}
									</SelectItem>
									<SelectItem
										className="text-sm capitalize"
										value="chosen_order_data"
									>
										{__('Choose an order', 'pdfdraft-pdf-invoices-for-woocommerce')}
									</SelectItem>
								</SelectContent>
							</Select>
						</div>
					)}
				/>
				{watchSourceType === 'chosen_order_data' && (
					<Controller
						control={form.control}
						name="woocommerce_data_source.order_id"
						render={({ field }) => (
							<div>
								<Popover open={isOpen} onOpenChange={onToggle} modal={false}>
									{orderQuery.isLoading ? (
										<></>
									) : (
										<PopoverTrigger asChild>
											<Button
												variant="ghost"
												role="combobox"
												className="border-input ring-offset-background placeholder:text-muted-foreground flex h-[38px] w-full min-w-[120px] items-center justify-between whitespace-nowrap rounded border bg-transparent px-3 py-2 text-sm shadow-none focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1"
											>
												<span>
													{orderQuery.data?.id
														? sprintf(
																'#%1$s - %2$s',
																orderQuery.data.id,
																'name',
															)
														: __('Select an order', 'pdfdraft-pdf-invoices-for-woocommerce')}
												</span>
												<ChevronDown
													size={12}
													className="!size-3 shrink-0 opacity-50"
												/>
											</Button>
										</PopoverTrigger>
									)}
									<PopoverContent
										className="p-0 shadow-none"
										align="center"
										side="bottom"
										sideOffset={15}
										onCloseAutoFocus={(e) => e.preventDefault()}
									>
										<Command>
											<CommandInput
												value={orderFilters.search}
												onValueChange={(v) => {
													setOrderFilters((prev) => ({
														...prev,
														search: v,
													}));
													setSearchTerm(v);
												}}
												placeholder={__('Search order...')}
											/>
											<CommandList>
												{(isLoading || ordersQuery.isLoading) && (
													<CommandLoading className="grid min-h-10 place-items-center">
														<LoaderCircle className="animate-spin" size={18} />
													</CommandLoading>
												)}
												{isError && !isLoading && (
													<div className="py-6 text-center text-sm">
														{__(
															'Something went wrong!',
															'pdfdraft-pdf-invoices-for-woocommerce',
														)}
													</div>
												)}
												{!isError &&
													!isLoading &&
													!ordersQuery.isLoading &&
													!orders.length && (
														<CommandEmpty>
															{sprintf(
																__(
																	'Sorry, we couldn’t find any results for “%s”. Try searching something related.',
																	'pdfdraft-pdf-invoices-for-woocommerce',
																),
																'',
															)}
														</CommandEmpty>
													)}
												<CommandGroup>
													<ScrollAreaPrimitive.Root className="relative h-52 overflow-hidden">
														<ScrollAreaPrimitive.Viewport
															onScroll={() => {}}
															className="h-full w-full rounded-[inherit]"
														>
															{orders.map((f) => (
																<CommandItem
																	key={f.id}
																	value={f.id.toString()}
																	onSelect={() => {
																		queryClient.setQueryData(
																			['order'],
																			() => f,
																		);
																		form.setValue(
																			'woocommerce_data_source.order_id',
																			f.id,
																		);
																		onClose();
																	}}
																>
																	<div className="space-y-1">
																		<span className="block text-sm text-[#383838]">
																			{sprintf('#%1$s - %2$s', f.id, 'name')}
																		</span>
																		<span className="block text-xs text-[#4E4E4E]">
																			{format(f.date_created, 'MMMM d, yyyy')}
																		</span>
																	</div>
																</CommandItem>
															))}
															{ordersQuery?.hasNextPage && (
																<CommandItem className="flex items-center justify-center">
																	<LoaderCircle
																		className="pointer-events-none animate-spin"
																		size={16}
																	/>
																</CommandItem>
															)}
														</ScrollAreaPrimitive.Viewport>
														<ScrollAreaPrimitive.Scrollbar className="flex h-full w-2.5 touch-none select-none border-l border-l-transparent p-[1px] transition-colors">
															<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-[#575757]" />
														</ScrollAreaPrimitive.Scrollbar>
														<ScrollAreaPrimitive.Corner />
													</ScrollAreaPrimitive.Root>
												</CommandGroup>
											</CommandList>
										</Command>
									</PopoverContent>
								</Popover>
							</div>
						)}
					/>
				)}
			</form>
		</div>
	);
});

export const Settings = () => (
	<QueryClientProvider client={queryClient}>
		<SettingsInner />
	</QueryClientProvider>
);
