import { User, Users } from "lucide-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import type { MetaFunction } from "react-router";
import { Link, useFetcher, useLoaderData } from "react-router";
import { Alert } from "~/components/Alert";
import { LinkButton } from "~/components/elements/Button";
import { SendouDialog } from "~/components/elements/Dialog";
import { Flag } from "~/components/Flag";
import { FormMessage } from "~/components/FormMessage";
import { FriendCodePopover } from "~/components/FriendCodePopover";
import { Image } from "~/components/Image";
import { LocaleTime } from "~/components/LocaleTime";
import { LocaleTimeRange } from "~/components/LocaleTimeRange";
import { Main } from "~/components/Main";
import { SubmitButton } from "~/components/SubmitButton";
import type { Tables } from "~/db/tables";
import { useUser } from "~/features/auth/core/user";
import type * as Seasons from "~/features/mmr/core/Seasons";
import { useDateTimeFormat } from "~/hooks/intl/useDateTimeFormat";
import { useAutoRerender } from "~/hooks/useAutoRerender";
import { useHasRole } from "~/modules/permissions/hooks";
import { metaTags, type SerializeFrom } from "~/utils/remix";
import type { SendouRouteHandle } from "~/utils/remix.server";
import {
	LEADERBOARDS_PAGE,
	LOG_IN_URL,
	MATCH_PROFILE_PAGE,
	navIconUrl,
	SENDOUQ_INFO_PAGE,
	SENDOUQ_LOOKING_PREVIEW_PAGE,
	SENDOUQ_PAGE,
	SENDOUQ_RULES_PAGE,
	SENDOUQ_STREAMS_PAGE,
	userSeasonsPage,
} from "~/utils/urls";
import { SendouButton } from "../../../components/elements/Button";
import { SendouPopover } from "../../../components/elements/Popover";
import { action } from "../actions/q.server";
import { loader } from "../loaders/q.server";
import { FULL_GROUP_SIZE } from "../q-constants";
import { userCanJoinQueueAt } from "../q-utils";

export { action, loader };

import styles from "./q.module.css";

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

export const meta: MetaFunction = (args) => {
	return metaTags({
		title: "SendouQ",
		description:
			"Splatoon 3 competitive ladder. Join by yourself or with your team and play ranked matches.",
		location: args.location,
	});
};

export default function QPage() {
	const { t } = useTranslation(["q"]);
	const [dialogOpen, setDialogOpen] = React.useState(true);
	const user = useUser();
	const data = useLoaderData<typeof loader>();
	const fetcher = useFetcher();
	const { formatter: joinTimeFormatter } = useDateTimeFormat({
		day: "numeric",
		month: "numeric",
		hour: "numeric",
		minute: "numeric",
	});

	const queueJoinStatus =
		user && data.friendCode ? userCanJoinQueueAt(user, data.friendCode) : null;

	return (
		<Main halfWidth className="stack lg">
			<div className="stack md">
				{data.season ? (
					<ActiveSeasonInfo season={data.season} />
				) : data.upcomingSeason ? (
					<UpcomingSeasonInfo season={data.upcomingSeason} />
				) : (
					<NoUpcomingSeasonInfo />
				)}
				<Clocks />
			</div>
			{data.season ? (
				<>
					{data.groupInvitedTo === null ? (
						<Alert variation="WARNING">{t("q:front.inviteCodeWrong")}</Alert>
					) : null}
					{!data.friendCode &&
					data.groupInvitedTo &&
					data.groupInvitedTo.members.length < FULL_GROUP_SIZE ? (
						<Alert variation="WARNING">{t("q:front.noFriendCode")}</Alert>
					) : null}
					{queueJoinStatus === "NOW" &&
					data.groupInvitedTo &&
					data.groupInvitedTo.members.length < FULL_GROUP_SIZE ? (
						<JoinTeamDialog
							open={dialogOpen}
							close={() => setDialogOpen(false)}
							members={data.groupInvitedTo.members}
						/>
					) : null}
					{user?.friendCode ? (
						<fetcher.Form className="stack md" method="post">
							<input type="hidden" name="_action" value="JOIN_QUEUE" />
							<div className="stack horizontal md items-center mt-4 mx-auto">
								<SubmitButton
									icon={<Users />}
									isDisabled={queueJoinStatus !== "NOW"}
								>
									{t("q:front.actions.joinWithGroup")}
								</SubmitButton>
								<SubmitButton
									name="direct"
									value="true"
									state={fetcher.state}
									icon={<User />}
									variant="outlined"
									isDisabled={queueJoinStatus !== "NOW"}
									testId="join-solo-button"
								>
									{t("q:front.actions.joinSolo")}
								</SubmitButton>
							</div>
							{queueJoinStatus instanceof Date ? (
								<div className="text-lighter text-xs text-center text-warning">
									{t("q:front.freshAccountWait", {
										time: joinTimeFormatter.format(queueJoinStatus) ?? "",
									})}
								</div>
							) : (
								<PreviewQueueButton />
							)}
						</fetcher.Form>
					) : user ? (
						<div className="stack md items-center">
							<FriendCodePopover />
							<div className="text-lighter text-xs text-center">
								{t("q:front.noFriendCodeHelp")}
							</div>
						</div>
					) : (
						<form
							className="stack md items-center"
							action={LOG_IN_URL}
							method="post"
						>
							<SendouButton size="big" type="submit">
								{t("q:front.actions.logIn")}
							</SendouButton>
						</form>
					)}
				</>
			) : null}
			{user?.friendCode ? (
				<div className="stack items-center">
					<FriendCodePopover size="small" />
				</div>
			) : null}
			<QLinks />
		</Main>
	);
}

const countries = [
	{
		id: 1,
		countryCode: "US",
		timeZone: "America/Los_Angeles",
		city: "la",
	},
	{ id: 2, countryCode: "US", timeZone: "America/New_York", city: "nyc" },
	{ id: 3, countryCode: "FR", timeZone: "Europe/Paris", city: "paris" },
	{ id: 4, countryCode: "JP", timeZone: "Asia/Tokyo", city: "tokyo" },
] as const;
function Clocks() {
	const { t } = useTranslation(["q"]);
	const now = useAutoRerender();

	return (
		<div className={styles.clocksContainer}>
			{countries.map((country) => {
				return (
					<div key={country.id} className={styles.clock}>
						<div className={styles.clockCountry}>
							{t(`q:front.cities.${country.city}`)}
						</div>
						<Flag countryCode={country.countryCode} />
						<LocaleTime
							date={now}
							options={{
								timeZone: country.timeZone,
								weekday: "long",
							}}
						/>
						<LocaleTime
							date={now}
							options={{
								timeZone: country.timeZone,
								hour: "numeric",
								minute: "numeric",
							}}
						/>
					</div>
				);
			})}
		</div>
	);
}

function JoinTeamDialog({
	open,
	close,
	members,
}: {
	open: boolean;
	close: () => void;
	members: {
		username: string;
		role: Tables["GroupMember"]["role"];
	}[];
}) {
	const { t, i18n } = useTranslation(["q"]);
	const fetcher = useFetcher();

	return (
		<SendouDialog
			isOpen={open}
			onClose={close}
			isDismissable
			className="text-center"
			heading={t("q:front.join.header", {
				members: new Intl.ListFormat(i18n.language).format(
					members.map((m) => m.username),
				),
			})}
		>
			<fetcher.Form
				className="stack horizontal justify-center md mt-6 flex-wrap"
				method="post"
			>
				<SubmitButton _action="JOIN_TEAM" state={fetcher.state}>
					{t("q:front.join.joinAction")}
				</SubmitButton>
				<FormMessage type="info">
					{t("q:front.join.friendSuggestion")}
				</FormMessage>
			</fetcher.Form>
		</SendouDialog>
	);
}

function ActiveSeasonInfo({
	season,
}: {
	season: SerializeFrom<Seasons.ListItem>;
}) {
	const { t } = useTranslation(["q"]);

	const dateOptions: Intl.DateTimeFormatOptions = {
		month: "numeric",
		day: "numeric",
		hour: "numeric",
		minute: "numeric",
	};

	return (
		<div className="text-lighter text-xs text-center">
			{t("q:front.seasonOpen", { nth: season.nth })}{" "}
			<b>
				<LocaleTimeRange
					from={new Date(season.starts)}
					to={new Date(season.ends)}
					options={dateOptions}
					inline
				/>
			</b>
		</div>
	);
}

function QLinks() {
	const { t } = useTranslation(["q"]);
	const user = useUser();

	return (
		<div className="stack sm">
			<QLink
				navIcon="articles"
				url={SENDOUQ_INFO_PAGE}
				title={t("q:front.nav.info.title")}
				subText={t("q:front.nav.info.description")}
			/>
			{user ? (
				<QLink
					navIcon="settings"
					url={MATCH_PROFILE_PAGE}
					title={t("q:front.nav.settings.title")}
					subText={t("q:front.nav.settings.description")}
				/>
			) : null}
			<QLink
				navIcon="vods"
				url={SENDOUQ_STREAMS_PAGE}
				title={t("q:front.nav.streams.title")}
				subText={t("q:front.nav.streams.description")}
			/>
			<QLink
				navIcon="leaderboards"
				url={LEADERBOARDS_PAGE}
				title={t("q:front.nav.leaderboards.title")}
				subText={t("q:front.nav.leaderboards.description")}
			/>
			{user ? (
				<QLink
					navIcon="u"
					url={userSeasonsPage({ user })}
					title={t("q:front.nav.mySeason.title")}
					subText={t("q:front.nav.mySeason.description")}
				/>
			) : null}
			<QLink
				navIcon="articles"
				url={SENDOUQ_RULES_PAGE}
				title={t("q:front.nav.rules.title")}
				subText={t("q:front.nav.rules.description")}
			/>
		</div>
	);
}

function QLink({
	url,
	navIcon,
	title,
	subText,
}: {
	url: string;
	navIcon: string;
	title: string;
	subText: string;
}) {
	return (
		<Link to={url} className={styles.frontPageLink}>
			<Image path={navIconUrl(navIcon)} alt="" width={32} />
			<div>
				{title}
				<div className={styles.linkSubText}>{subText}</div>
			</div>
		</Link>
	);
}

function UpcomingSeasonInfo({
	season,
}: {
	season: SerializeFrom<Seasons.ListItem>;
}) {
	const { t } = useTranslation(["q"]);
	const { formatter } = useDateTimeFormat({
		month: "numeric",
		day: "numeric",
		hour: "numeric",
		minute: "numeric",
	});

	return (
		<div className="font-semi-bold text-center text-sm">
			{t("q:front.upcomingSeason.header")}
			<br />
			{t("q:front.upcomingSeason.date", {
				nth: season.nth,
				date: formatter.format(new Date(season.starts)) ?? "",
			})}
		</div>
	);
}

function NoUpcomingSeasonInfo() {
	const { t } = useTranslation(["q"]);

	return (
		<div className="font-semi-bold text-center text-sm">
			{t("q:front.upcomingSeason.header")}
			<br />
			{t("q:front.noUpcomingSeason")}
		</div>
	);
}

function PreviewQueueButton() {
	const isSupporter = useHasRole("SUPPORTER");
	const { t } = useTranslation(["q"]);

	if (!isSupporter) {
		return (
			<SendouPopover
				trigger={
					<SendouButton className="mx-auto text-xs" variant="minimal">
						{t("q:front.preview")}
					</SendouButton>
				}
			>
				{t("q:front.preview.explanation")}
			</SendouPopover>
		);
	}

	return (
		<LinkButton
			to={SENDOUQ_LOOKING_PREVIEW_PAGE}
			variant="minimal"
			size="small"
		>
			{t("q:front.preview")}
		</LinkButton>
	);
}
