import clsx from "clsx";
import { X } from "lucide-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import type { MetaFunction, ShouldRevalidateFunction } from "react-router";
import { useLoaderData, useSearchParams } from "react-router";
import { SendouButton } from "~/components/elements/Button";
import { SendouSwitch } from "~/components/elements/Switch";
import {
	SendouTab,
	SendouTabList,
	SendouTabPanel,
	SendouTabs,
} from "~/components/elements/Tabs";
import { Label } from "~/components/Label";
import { Main } from "~/components/Main";
import type { SendouRouteHandle } from "~/utils/remix.server";
import { artPage, navIconUrl } from "~/utils/urls";
import { metaTags, type SerializeFrom } from "../../../utils/remix";
import { FILTERED_TAG_KEY_SEARCH_PARAM_KEY } from "../art-constants";
import { ArtGrid } from "../components/ArtGrid";
import { TagSelect } from "../components/TagSelect";
import { loader } from "../loaders/art.server";

export { loader };

const OPEN_COMMISIONS_KEY = "open";
const TAB_KEY = "tab";
const TABS = {
	RECENTLY_UPLOADED: "recently-uploaded",
	SHOWCASE: "showcase",
} as const;

export const shouldRevalidate: ShouldRevalidateFunction = (args) => {
	const currentFilteredTag = args.currentUrl.searchParams.get(
		FILTERED_TAG_KEY_SEARCH_PARAM_KEY,
	);
	const nextFilteredTag = args.nextUrl.searchParams.get(
		FILTERED_TAG_KEY_SEARCH_PARAM_KEY,
	);

	if (currentFilteredTag === nextFilteredTag) return false;

	return args.defaultShouldRevalidate;
};

export const handle: SendouRouteHandle = {
	i18n: ["art"],
	breadcrumb: () => ({
		imgPath: navIconUrl("art"),
		href: artPage(),
		type: "IMAGE",
	}),
};

export const meta: MetaFunction = (args) => {
	const data = args.loaderData as SerializeFrom<typeof loader> | null;

	if (!data) return [];

	return metaTags({
		title: "Art",
		ogTitle: "Splatoon art showcase",
		description:
			"Splatoon art filterable by various tags. Find artist to commission for your own custom art. Includes various styles such as traditional, digital, 3D and SFM.",
		location: args.location,
	});
};

export default function ArtPage() {
	const { t } = useTranslation(["art", "common", "forms"]);
	const data = useLoaderData<typeof loader>();
	const [searchParams, setSearchParams] = useSearchParams();
	const switchId = React.useId();

	const selectedTab = searchParams.get(TAB_KEY) ?? TABS.RECENTLY_UPLOADED;
	const filteredTag = searchParams.get(FILTERED_TAG_KEY_SEARCH_PARAM_KEY);
	const showOpenCommissions = searchParams.get(OPEN_COMMISIONS_KEY) === "true";

	const showcaseArts = !showOpenCommissions
		? data.showcaseArts
		: data.showcaseArts.filter((art) => art.author?.commissionsOpen);

	const recentlyUploadedArts = !showOpenCommissions
		? data.recentlyUploadedArts
		: data.recentlyUploadedArts.filter((art) => art.author?.commissionsOpen);

	return (
		<Main className="stack lg">
			<div className="stack horizontal md justify-between items-center flex-wrap">
				<div className="stack horizontal sm text-sm font-semi-bold">
					<SendouSwitch
						isSelected={showOpenCommissions}
						onChange={() =>
							setSearchParams((prev) => {
								prev.set(OPEN_COMMISIONS_KEY, String(!showOpenCommissions));
								return prev;
							})
						}
						id={switchId}
					/>
					<Label htmlFor={switchId} className="m-auto-0">
						{t("forms:labels.profileCommissionsOpen")}
					</Label>
				</div>
				<div
					className={clsx({
						invisible: selectedTab !== TABS.SHOWCASE,
					})}
				>
					<TagSelect
						key={filteredTag}
						tags={data.allTags}
						onSelectionChange={(tagName) => {
							setSearchParams(
								(prev) => {
									prev.set(
										FILTERED_TAG_KEY_SEARCH_PARAM_KEY,
										tagName as string,
									);
									return prev;
								},
								{ replace: true },
							);
						}}
					/>
				</div>
			</div>
			{filteredTag ? (
				<div className="text-xs text-lighter stack md horizontal items-center">
					{t("art:filteringByTag", { tag: filteredTag })}
					<SendouButton
						size="small"
						variant="minimal-destructive"
						icon={<X />}
						onPress={() => {
							setSearchParams(
								(prev) => {
									prev.delete(FILTERED_TAG_KEY_SEARCH_PARAM_KEY);
									return prev;
								},
								{ replace: true },
							);
						}}
						data-testid="clear-filter-button"
					>
						{t("common:actions.clear")}
					</SendouButton>
				</div>
			) : null}
			<SendouTabs
				selectedKey={selectedTab}
				onSelectionChange={(key) => {
					setSearchParams(
						(prev) => {
							prev.set(TAB_KEY, key as string);
							if (key === TABS.RECENTLY_UPLOADED) {
								prev.delete(FILTERED_TAG_KEY_SEARCH_PARAM_KEY);
							}
							return prev;
						},
						{ replace: true },
					);
				}}
			>
				<SendouTabList>
					<SendouTab id={TABS.RECENTLY_UPLOADED}>
						{t("art:tabs.recentlyUploaded")}
					</SendouTab>
					<SendouTab id={TABS.SHOWCASE}>{t("art:tabs.showcase")}</SendouTab>
				</SendouTabList>
				<SendouTabPanel id={TABS.RECENTLY_UPLOADED}>
					<ArtGrid arts={recentlyUploadedArts} showUploadDate />
				</SendouTabPanel>
				<SendouTabPanel id={TABS.SHOWCASE}>
					{filteredTag && showcaseArts.length === 0 ? (
						<div className="no-results mt-4">
							{t("art:noArtForTag", { tag: filteredTag })}
						</div>
					) : (
						<ArtGrid arts={showcaseArts} />
					)}
				</SendouTabPanel>
			</SendouTabs>
		</Main>
	);
}
