import { Check, Clipboard, Trash } from "lucide-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link, Outlet, useFetcher, useLoaderData } from "react-router";
import { Avatar } from "~/components/Avatar";
import { SendouButton } from "~/components/elements/Button";
import { FormWithConfirm } from "~/components/FormWithConfirm";
import { Label } from "~/components/Label";
import { Main } from "~/components/Main";
import { SubmitButton } from "~/components/SubmitButton";
import { action } from "~/features/associations/actions/associations.server";
import {
	type AssociationsLoaderData,
	loader,
} from "~/features/associations/loaders/associations.server";
import { useUser } from "~/features/auth/core/user";
import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
import { useHasPermission } from "~/modules/permissions/hooks";
import type { SendouRouteHandle } from "~/utils/remix.server";
import { associationsPage, userPage } from "~/utils/urls";

export { action, loader };

export const handle: SendouRouteHandle = {
	i18n: "scrims",
};

export default function AssociationsPage() {
	const data = useLoaderData<typeof loader>();

	return (
		<Main className="stack lg">
			<Outlet />
			<div className="stack sm">
				<Header />
			</div>
			<JoinForm />
			{data.associations.map((association) => (
				<Association key={association.id} association={association} />
			))}
		</Main>
	);
}

function Header() {
	const { t } = useTranslation(["scrims"]);

	return (
		<div>
			<h1 className="text-xl">{t("scrims:associations.title")}</h1>
			<div className="text-sm text-lighter">
				{t("scrims:associations.explanation")}
			</div>
		</div>
	);
}

function JoinForm() {
	const data = useLoaderData<typeof loader>();
	const fetcher = useFetcher();
	const { t } = useTranslation(["common", "scrims"]);

	if (!data.toJoin) return null;

	return (
		<fetcher.Form method="post" className="stack horizontal md items-center">
			<input type="hidden" name="inviteCode" value={data.toJoin.inviteCode} />
			<Label spaced={false}>
				{t("scrims:associations.join.title", {
					name: data.toJoin.association.name,
				})}
			</Label>
			<SubmitButton
				size="small"
				_action="JOIN_ASSOCIATION"
				state={fetcher.state}
			>
				{t("common:actions.join")}
			</SubmitButton>
		</fetcher.Form>
	);
}

function Association({
	association,
}: {
	association: AssociationsLoaderData["associations"][number];
}) {
	const { t } = useTranslation(["common", "scrims"]);
	const user = useUser();
	const canManage = useHasPermission(association, "MANAGE");

	return (
		<section>
			<div className="stack horizontal sm items-center justify-between">
				<h2 className="text-lg"> {association.name}</h2>
				{canManage ? (
					<FormWithConfirm
						dialogHeading={t("scrims:associations.delete.title", {
							name: association.name,
						})}
						fields={[
							["associationId", association.id],
							["_action", "DELETE_ASSOCIATION"],
						]}
					>
						<SendouButton
							shape="square"
							icon={<Trash className="small-icon" />}
							className="small-text"
							variant="minimal-destructive"
							type="submit"
							data-testid="delete-association"
						/>
					</FormWithConfirm>
				) : null}
			</div>
			<div className="text-sm text-lighter">
				{t("scrims:associations.admin", {
					username: association.members?.find((m) => m.role === "ADMIN")
						?.username,
				})}
			</div>
			{!canManage ? (
				<FormWithConfirm
					dialogHeading={t("scrims:associations.leave.title", {
						name: association.name,
					})}
					fields={[
						["_action", "LEAVE_ASSOCIATION"],
						["associationId", association.id],
					]}
					submitButtonText={t("scrims:associations.leave.action")}
				>
					<SendouButton
						variant="minimal-destructive"
						type="submit"
						size="small"
						className="my-2"
						data-testid="leave-team-button"
					>
						{t("scrims:associations.leave.action")}
					</SendouButton>
				</FormWithConfirm>
			) : null}
			<div className="stack sm mt-4">
				{association.members?.map((member) => (
					<AssociationMember
						key={member.id}
						member={member}
						associationId={association.id}
						showControls={canManage && member.id !== user?.id}
					/>
				))}
			</div>
			{association.inviteCode ? (
				<AssociationInviteCodeActions
					associationId={association.id}
					inviteCode={association.inviteCode}
				/>
			) : null}
		</section>
	);
}

function AssociationInviteCodeActions({
	associationId,
	inviteCode,
}: {
	associationId: number;
	inviteCode: string;
}) {
	const { t } = useTranslation(["common", "scrims"]);
	const { copyToClipboard, copySuccess } = useCopyToClipboard();
	const fetcher = useFetcher();
	const id = React.useId();

	const inviteLink = `https://sendou.ink${associationsPage(inviteCode)}`;

	return (
		<div className="mt-6">
			<label htmlFor={id}>{t("scrims:associations.shareLink.title")}</label>
			<div className="stack horizontal sm items-center">
				<input type="text" value={inviteLink} readOnly id={id} />
				<SendouButton
					shape="square"
					variant={copySuccess ? "outlined-success" : "outlined"}
					onPress={() => copyToClipboard(inviteLink)}
					icon={copySuccess ? <Check /> : <Clipboard />}
					aria-label="Copy to clipboard"
				/>
			</div>
			<fetcher.Form method="post">
				<input type="hidden" name="associationId" value={associationId} />
				<SubmitButton
					variant="minimal-destructive"
					size="small"
					_action="REFRESH_INVITE_CODE"
					state={fetcher.state}
				>
					{t("scrims:associations.shareLink.reset")}
				</SubmitButton>
			</fetcher.Form>
		</div>
	);
}

function AssociationMember({
	member,
	associationId,
	showControls,
}: {
	member: NonNullable<
		AssociationsLoaderData["associations"][number]["members"]
	>[number];
	associationId: number;
	showControls?: boolean;
}) {
	const { t } = useTranslation(["common", "scrims"]);

	return (
		<div className="stack horizontal sm items-center justify-between">
			<Link
				to={userPage(member)}
				className="text-main-forced stack horizontal sm"
			>
				<Avatar size="xxs" user={member} />
				{member.username}
			</Link>
			{showControls ? (
				<FormWithConfirm
					dialogHeading={t("scrims:associations.removeMember.title", {
						username: member.username,
					})}
					submitButtonText={t("common:actions.remove")}
					fields={[
						["userId", member.id],
						["associationId", associationId],
						["_action", "REMOVE_MEMBER"],
					]}
				>
					<SendouButton
						shape="square"
						icon={<Trash className="small-icon" />}
						className="small-text"
						variant="minimal-destructive"
						size="small"
						type="submit"
					/>
				</FormWithConfirm>
			) : null}
		</div>
	);
}
