"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 ;
}
const actions = (
);
const resultsHeaderRight = urlState.q ? (
{urlState.q}
) : 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 (
);
}