import clsx from "clsx";
import { differenceInDays } from "date-fns";
import { ShieldMinus } from "lucide-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
import { Avatar } from "~/components/Avatar";
import { SendouButton } from "~/components/elements/Button";
import {
	SendouTab,
	SendouTabList,
	SendouTabPanel,
	SendouTabs,
} from "~/components/elements/Tabs";
import { Flag } from "~/components/Flag";
import { InfoPopover } from "~/components/InfoPopover";
import { Placement } from "~/components/Placement";
import { Table } from "~/components/Table";
import type { Standing } from "~/features/tournament-bracket/core/Bracket";
import { useSpoilerFree } from "~/hooks/useSpoilerFree";
import {
	SPR_INFO_URL,
	tournamentMatchPage,
	tournamentTeamPage,
} from "~/utils/urls";
import * as Standings from "../core/Standings";
import styles from "../tournament.module.css";
import { TOURNAMENT } from "../tournament-constants";
import { useTournament } from "./to.$id";

export default function TournamentResultsPage() {
	const { t } = useTranslation(["common"]);
	const tournament = useTournament();
	const { isCensored, reveal } = useSpoilerFree();

	const withinSpoilerWindow =
		differenceInDays(new Date(), tournament.ctx.startTime) <
		TOURNAMENT.VOD_VISIBILITY_DAYS;
	const censored = withinSpoilerWindow && isCensored(tournament.ctx.id);

	if (censored) {
		return (
			<div className={styles.spoilerRevealContainer}>
				<SendouButton
					variant="outlined"
					size="big"
					onPress={() => reveal(tournament.ctx.id)}
					icon={<ShieldMinus />}
				>
					{t("common:spoilerFree.showResults")}
				</SendouButton>
			</div>
		);
	}

	const standingsResult = Standings.tournamentStandings(tournament);

	if (standingsResult.type === "single") {
		if (standingsResult.standings.length === 0) {
			return (
				<div className="text-center text-lg font-semi-bold text-lighter">
					No team finished yet, check back later
				</div>
			);
		}

		return (
			<div>
				<ResultsTable standings={standingsResult.standings} />
			</div>
		);
	}

	return (
		<SendouTabs>
			<SendouTabList>
				{standingsResult.standings.map(({ div }) => (
					<SendouTab key={div} id={div}>
						{div}
					</SendouTab>
				))}
			</SendouTabList>
			{standingsResult.standings.map(({ div, standings }) => (
				<SendouTabPanel key={div} id={div}>
					{standings.length === 0 ? (
						<div className="text-center text-lg font-semi-bold text-lighter">
							No team finished yet, check back later
						</div>
					) : (
						<ResultsTable standings={standings} />
					)}
				</SendouTabPanel>
			))}
		</SendouTabs>
	);
}

function ResultsTable({ standings }: { standings: Standing[] }) {
	const tournament = useTournament();

	let lastRenderedPlacement = 0;
	let rowDarkerBg = false;

	return (
		<Table noRowHover>
			<thead>
				<tr>
					<th>Standing</th>
					<th>Team</th>
					<th>Roster</th>
					<th>Seed</th>
					{tournament.ctx.isFinalized ? (
						<th
							className="stack horizontal sm items-center"
							data-testid="spr-header"
						>
							SPR{" "}
							<InfoPopover tiny>
								<a
									href={SPR_INFO_URL}
									target="_blank"
									rel="noopener noreferrer"
								>
									Seed Performance Rating
								</a>
							</InfoPopover>
						</th>
					) : null}
					<th>Matches</th>
				</tr>
			</thead>
			<tbody>
				{standings.map((standing, i) => {
					const placement =
						lastRenderedPlacement === standing.placement
							? null
							: standing.placement;
					lastRenderedPlacement = standing.placement;

					if (standing.placement !== standings[i - 1]?.placement) {
						rowDarkerBg = !rowDarkerBg;
					}

					const teamLogoSrc = tournament.tournamentTeamLogoSrc(standing.team);

					const spr = Standings.calculateSPR({
						standings,
						teamId: standing.team.id,
					});

					return (
						<tr
							key={standing.team.id}
							className={rowDarkerBg ? styles.standingsRowAlt : undefined}
						>
							<td className="text-md">
								{typeof placement === "number" ? (
									<Placement placement={placement} size={36} />
								) : null}{" "}
							</td>
							<td>
								<Link
									to={tournamentTeamPage({
										tournamentId: tournament.ctx.id,
										tournamentTeamId: standing.team.id,
									})}
									className={styles.standingsTeamName}
									data-testid="result-team-name"
									title={standing.team.name}
								>
									<Avatar
										size="xs"
										url={teamLogoSrc}
										identiconInput={standing.team.name}
									/>
									<span className={styles.standingsTeamNameText}>
										{standing.team.name}
									</span>
								</Link>
							</td>
							<td>
								{standing.team.members.map((player) => (
									<div
										key={player.userId}
										className="stack xxs horizontal items-center"
									>
										{player.country ? (
											<Flag countryCode={player.country} tiny />
										) : null}
										{player.username}
									</div>
								))}
							</td>
							<td className="text-sm">{standing.team.seed}</td>
							{tournament.ctx.isFinalized ? (
								<td className="text-sm">
									{spr > 0 ? "+" : ""}
									{spr}
								</td>
							) : null}
							<td>
								<MatchHistoryRow teamId={standing.team.id} />
							</td>
						</tr>
					);
				})}
			</tbody>
		</Table>
	);
}

function MatchHistoryRow({ teamId }: { teamId: number }) {
	const tournament = useTournament();

	const teamMatches = Standings.matchesPlayed({
		tournament,
		teamId,
	});

	return (
		<div className="stack horizontal xs">
			{teamMatches.map((match, i) => {
				const bracketChanged =
					i !== 0 && teamMatches[i - 1].bracketIdx !== match.bracketIdx;

				return (
					<React.Fragment key={match.id}>
						{bracketChanged ? (
							<div className={styles.standingsDivider} />
						) : null}
						<MatchResultSquare result={match.result} matchId={match.id}>
							{match.vsSeed}
						</MatchResultSquare>
					</React.Fragment>
				);
			})}
		</div>
	);
}

function MatchResultSquare({
	result,
	matchId,
	children,
}: {
	result: "win" | "loss";
	matchId: number;
	children: React.ReactNode;
}) {
	const tournament = useTournament();

	return (
		<Link
			to={tournamentMatchPage({
				matchId,
				tournamentId: tournament.ctx.id,
			})}
			className={clsx(styles.standingsMatchResultSquare, {
				[styles.standingsMatchResultSquareWin]: result === "win",
				[styles.standingsMatchResultSquareLoss]: result === "loss",
			})}
		>
			{children}
		</Link>
	);
}
