"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 { isAdminLike as isAdminLikeRole } from "@/lib/frontend/auth/roles";

import { parseSearchUrlState } 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 {
	buildSearchHref,
	buildSearchKey,
	getScopeLabel,
	needsMultiBranchSelectionHint,
	buildNextStateForScopeChange,
	buildNextStateForToggleBranch,
	buildNextStateForClearAllBranches,
	buildHrefForSingleBranchSwitch,
} from "@/lib/frontend/search/pageHelpers";
import {
	loadSearchHistory,
	addSearchHistoryEntry,
	clearSearchHistory,
	buildSearchHrefFromEntry,
	DEFAULT_SEARCH_HISTORY_MAX_ITEMS,
} from "@/lib/frontend/search/history";

import { buildDateFilterValidationError } from "@/lib/frontend/search/dateFilterValidation";

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";

export default function SearchPage({ branch: routeBranch }) {
	const router = useRouter();
	const searchParams = useSearchParams();
	const { status: authStatus, user } = useAuth();
	const userId =
		typeof user?.userId === "string" && user.userId.trim()
			? user.userId.trim()
			: null;

	const isAuthenticated = authStatus === "authenticated" && user;
	const isAdminLike = isAuthenticated && isAdminLikeRole(user.role);

	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(() => {
		return buildSearchKey({ routeBranch, urlState });
	}, [routeBranch, urlState]);

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

	const [recentSearches, setRecentSearches] = React.useState([]);
	React.useEffect(() => {
		if (!userId) {
			setRecentSearches([]);
			return;
		}

		setRecentSearches(loadSearchHistory(userId));
	}, [userId]);

	const historyWriteGuardRef = React.useRef("");
	React.useEffect(() => {
		historyWriteGuardRef.current = "";
	}, [userId]);

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

	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],
	);

	const localDateValidationError = React.useMemo(() => {
		return buildDateFilterValidationError({
			from: urlState.from,
			to: urlState.to,
		});
	}, [urlState.from, urlState.to]);

	const mappedLocalDateValidation = React.useMemo(() => {
		return mapSearchError(localDateValidationError);
	}, [localDateValidationError]);

	const formValidationError =
		mappedError?.kind === "validation"
			? mappedError
			: mappedLocalDateValidation?.kind === "validation"
				? mappedLocalDateValidation
				: null;

	React.useEffect(() => {
		// Trigger policy: store only executed searches that completed first-page loading successfully.
		if (!userId) return;
		if (query.status !== "success") return;
		if (typeof urlState.q !== "string" || !urlState.q.trim()) return;

		const writeKey = `${userId}|${searchKey}`;
		if (historyWriteGuardRef.current === writeKey) return;

		const nextEntries = addSearchHistoryEntry(
			userId,
			{
				routeBranch,
				q: urlState.q,
				scope: urlState.scope,
				branches: urlState.branches,
				limit: urlState.limit,
				from: urlState.from,
				to: urlState.to,
				createdAt: Date.now(),
			},
			{ maxItems: DEFAULT_SEARCH_HISTORY_MAX_ITEMS },
		);

		setRecentSearches(nextEntries);
		historyWriteGuardRef.current = writeKey;
	}, [
		userId,
		query.status,
		searchKey,
		routeBranch,
		urlState.q,
		urlState.scope,
		urlState.branches,
		urlState.limit,
		urlState.from,
		urlState.to,
	]);

	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(() => {
		pushStateToUrl({ ...urlState, q: qDraft });
	}, [pushStateToUrl, urlState, qDraft]);

	const handleScopeChange = React.useCallback(
		(nextScope) => {
			if (!isAdminLike) return;
			replaceStateToUrl(buildNextStateForScopeChange({ urlState, nextScope }));
		},
		[isAdminLike, urlState, replaceStateToUrl],
	);

	const handleToggleBranch = React.useCallback(
		(branchId) => {
			if (!isAdminLike) return;
			replaceStateToUrl(buildNextStateForToggleBranch({ urlState, branchId }));
		},
		[isAdminLike, urlState, replaceStateToUrl],
	);

	const handleClearAllBranches = React.useCallback(() => {
		if (!isAdminLike) return;
		replaceStateToUrl(buildNextStateForClearAllBranches({ urlState }));
	}, [isAdminLike, urlState, replaceStateToUrl]);

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

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

			const href = buildHrefForSingleBranchSwitch({ nextBranch, urlState });
			if (!href) return;

			router.push(href);
		},
		[isAdminLike, urlState, router],
	);

	const handleDateRangeChange = React.useCallback(
		({ from, to }) => {
			replaceStateToUrl({
				...urlState,
				from: from ?? null,
				to: to ?? null,
			});
		},
		[urlState, replaceStateToUrl],
	);

	const handleSelectRecentSearch = React.useCallback(
		(entry) => {
			const href = buildSearchHrefFromEntry(entry);
			if (!href) return;

			router.push(href);
		},
		[router],
	);

	const handleClearRecentSearches = React.useCallback(() => {
		if (!userId) return;

		clearSearchHistory(userId);
		setRecentSearches([]);
		historyWriteGuardRef.current = "";
	}, [userId]);

	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 scopeLabel = getScopeLabel({ routeBranch, urlState });

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

	const needsBranchSelection = needsMultiBranchSelectionHint({
		isAdminDev: isAdminLike,
		urlState,
	});

	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={isAdminLike}
					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}
					onClearAllBranches={handleClearAllBranches}
					limit={urlState.limit}
					onLimitChange={handleLimitChange}
					from={urlState.from}
					to={urlState.to}
					onDateRangeChange={handleDateRangeChange}
					validationError={formValidationError}
					recentSearches={recentSearches}
					onSelectRecentSearch={handleSelectRecentSearch}
					onClearRecentSearches={handleClearRecentSearches}
				/>
			</ExplorerSectionCard>

			<ExplorerSectionCard
				title="Ergebnisse"
				description={resultsDescription}
				headerRight={resultsHeaderRight}
			>
				<SearchResults
					branch={routeBranch}
					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>
	);
}
