"use client";

import React from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { RefreshCw } from "lucide-react";

import { useAuth } from "@/components/auth/authContext";
import { buildLoginUrl, LOGIN_REASONS } from "@/lib/frontend/authRedirect";
import { searchPath } from "@/lib/frontend/routes";
import { isValidBranchParam } from "@/lib/frontend/params";

import {
	parseSearchUrlState,
	serializeSearchUrlState,
	SEARCH_SCOPE,
} from "@/lib/frontend/search/urlState";
import { normalizeSearchUrlStateForUser } from "@/lib/frontend/search/normalizeState";
import { mapSearchError } from "@/lib/frontend/search/errorMapping";
import { useSearchQuery } from "@/lib/frontend/search/useSearchQuery";
import {
	useSearchBranches,
	BRANCH_LIST_STATE,
} from "@/lib/frontend/search/useSearchBranches";

import ExplorerPageShell from "@/components/explorer/ExplorerPageShell";
import ExplorerSectionCard from "@/components/explorer/ExplorerSectionCard";
import ForbiddenView from "@/components/system/ForbiddenView";
import { Button } from "@/components/ui/button";

import SearchForm from "@/components/search/SearchForm";
import SearchResults from "@/components/search/SearchResults";

function buildSearchHref({ routeBranch, state }) {
	const base = searchPath(routeBranch);
	const qs = serializeSearchUrlState(state);
	return qs ? `${base}?${qs}` : base;
}

export default function SearchPage({ branch: routeBranch }) {
	const router = useRouter();
	const searchParams = useSearchParams();
	const { status: authStatus, user } = useAuth();

	const isAuthenticated = authStatus === "authenticated" && user;
	const isAdminDev =
		isAuthenticated && (user.role === "admin" || user.role === "dev");

	const parsedUrlState = React.useMemo(() => {
		return parseSearchUrlState(searchParams, { routeBranch });
	}, [searchParams, routeBranch]);

	const urlState = React.useMemo(() => {
		return normalizeSearchUrlStateForUser(parsedUrlState, {
			routeBranch,
			user,
		});
	}, [parsedUrlState, routeBranch, user]);

	const searchKey = React.useMemo(() => {
		const qs = serializeSearchUrlState(urlState);
		return `${routeBranch}|${qs}`;
	}, [routeBranch, urlState]);

	const [qDraft, setQDraft] = React.useState(urlState.q || "");
	React.useEffect(() => {
		setQDraft(urlState.q || "");
	}, [urlState.q]);

	const branchesQuery = useSearchBranches({ enabled: isAdminDev });

	const query = useSearchQuery({
		searchKey,
		urlState,
		routeBranch,
		user,
		limit: urlState.limit,
	});

	const mappedError = React.useMemo(
		() => mapSearchError(query.error),
		[query.error]
	);
	const mappedLoadMoreError = React.useMemo(
		() => mapSearchError(query.loadMoreError),
		[query.loadMoreError]
	);

	React.useEffect(() => {
		if (mappedError?.kind !== "unauthenticated") return;

		const next =
			typeof window !== "undefined"
				? `${window.location.pathname}${window.location.search}`
				: searchPath(routeBranch);

		window.location.replace(
			buildLoginUrl({ reason: LOGIN_REASONS.EXPIRED, next })
		);
	}, [mappedError?.kind, routeBranch]);

	const pushStateToUrl = React.useCallback(
		(nextState) => {
			router.push(buildSearchHref({ routeBranch, state: nextState }));
		},
		[router, routeBranch]
	);

	const replaceStateToUrl = React.useCallback(
		(nextState) => {
			router.replace(buildSearchHref({ routeBranch, state: nextState }));
		},
		[router, routeBranch]
	);

	const handleSubmit = React.useCallback(() => {
		const nextState = {
			...urlState,
			q: qDraft,
		};

		pushStateToUrl(nextState);
	}, [urlState, qDraft, pushStateToUrl]);

	const handleScopeChange = React.useCallback(
		(nextScope) => {
			if (!isAdminDev) return;

			const nextState = {
				...urlState,
				scope: nextScope,
				branches: nextScope === SEARCH_SCOPE.MULTI ? urlState.branches : [],
			};

			replaceStateToUrl(nextState);
		},
		[isAdminDev, urlState, replaceStateToUrl]
	);

	const handleToggleBranch = React.useCallback(
		(branchId) => {
			if (!isAdminDev) return;

			const current = Array.isArray(urlState.branches) ? urlState.branches : [];
			const set = new Set(current);

			if (set.has(branchId)) set.delete(branchId);
			else set.add(branchId);

			const nextState = {
				...urlState,
				scope: SEARCH_SCOPE.MULTI,
				branches: Array.from(set),
			};

			replaceStateToUrl(nextState);
		},
		[isAdminDev, urlState, replaceStateToUrl]
	);

	const handleLimitChange = React.useCallback(
		(nextLimit) => {
			const nextState = {
				...urlState,
				limit: nextLimit,
			};

			replaceStateToUrl(nextState);
		},
		[urlState, replaceStateToUrl]
	);

	const handleSingleBranchChange = React.useCallback(
		(nextBranch) => {
			if (!isAdminDev) return;
			if (!isValidBranchParam(nextBranch)) return;

			const nextState = {
				...urlState,
				scope: SEARCH_SCOPE.SINGLE,
				branches: [],
			};

			const base = searchPath(nextBranch);
			const qs = serializeSearchUrlState(nextState);

			router.push(qs ? `${base}?${qs}` : base);
		},
		[isAdminDev, urlState, router]
	);

	if (mappedError?.kind === "forbidden") {
		return <ForbiddenView attemptedBranch={routeBranch} />;
	}

	const actions = (
		<Button
			variant="outline"
			size="sm"
			onClick={query.retry}
			disabled={!urlState.q || query.status === "loading"}
			title="Aktualisieren"
		>
			<RefreshCw className="h-4 w-4" />
			Aktualisieren
		</Button>
	);

	const resultsHeaderRight = urlState.q ? (
		<span className="rounded-md bg-muted px-2 py-1 text-xs text-muted-foreground">
			{urlState.q}
		</span>
	) : null;

	const multiCount = Array.isArray(urlState.branches)
		? urlState.branches.length
		: 0;

	const scopeLabel =
		urlState.scope === SEARCH_SCOPE.ALL
			? "Alle Niederlassungen"
			: urlState.scope === SEARCH_SCOPE.MULTI
			? multiCount > 0
				? `${multiCount} Niederlassung${multiCount === 1 ? "" : "en"}`
				: "Mehrere Niederlassungen"
			: `Niederlassung ${routeBranch}`;

	const resultsDescription = urlState.q
		? `Suchbereich: ${scopeLabel}`
		: "Geben Sie einen Suchbegriff ein, um zu starten.";

	const needsBranchSelection =
		isAdminDev &&
		urlState.scope === SEARCH_SCOPE.MULTI &&
		Boolean(urlState.q) &&
		multiCount === 0;

	return (
		<ExplorerPageShell
			title="Suche"
			description={`Lieferscheine durchsuchen • Niederlassung ${routeBranch}`}
			actions={actions}
		>
			<ExplorerSectionCard
				title="Suche"
				description="Suchbegriff und Suchbereich auswählen."
			>
				<SearchForm
					branch={routeBranch}
					qDraft={qDraft}
					onQDraftChange={setQDraft}
					onSubmit={handleSubmit}
					currentQuery={urlState.q}
					isSubmitting={query.status === "loading"}
					isAdminDev={isAdminDev}
					scope={urlState.scope}
					onScopeChange={handleScopeChange}
					onSingleBranchChange={handleSingleBranchChange}
					availableBranches={
						branchesQuery.status === BRANCH_LIST_STATE.READY &&
						Array.isArray(branchesQuery.branches)
							? branchesQuery.branches
							: []
					}
					branchesStatus={branchesQuery.status}
					selectedBranches={urlState.branches}
					onToggleBranch={handleToggleBranch}
					limit={urlState.limit}
					onLimitChange={handleLimitChange}
				/>
			</ExplorerSectionCard>

			<ExplorerSectionCard
				title="Ergebnisse"
				description={resultsDescription}
				headerRight={resultsHeaderRight}
			>
				<SearchResults
					branch={routeBranch}
					scope={urlState.scope}
					status={query.status}
					items={query.items}
					total={query.total}
					error={mappedError}
					onRetry={query.retry}
					nextCursor={query.nextCursor}
					onLoadMore={query.loadMore}
					isLoadingMore={query.isLoadingMore}
					loadMoreError={mappedLoadMoreError}
					needsBranchSelection={needsBranchSelection}
				/>
			</ExplorerSectionCard>
		</ExplorerPageShell>
	);
}
