import type {
  LinksFunction,
  LoaderArgs,
  V2_MetaFunction,
  SerializeFrom,
} from "@remix-run/node";
import { json } from "@remix-run/node";
import { Outlet, useLoaderData, useLocation } from "@remix-run/react";
import * as React from "react";
import invariant from "tiny-invariant";
import { z } from "zod";
import { Main } from "~/components/Main";
import { SubNav, SubNavLink } from "~/components/SubNav";
import { db } from "~/db";
import { userTopPlacements } from "~/features/top-search";
import { findVods } from "~/features/vods";
import { useTranslation } from "~/hooks/useTranslation";
import { useUser } from "~/modules/auth";
import { getUserId } from "~/modules/auth/user.server";
import { canAddCustomizedColorsToUserProfile } from "~/permissions";
import styles from "~/styles/u.css";
import { notFoundIfFalsy, type SendouRouteHandle } from "~/utils/remix";
import { discordFullName, makeTitle } from "~/utils/strings";
import {
  isCustomUrl,
  navIconUrl,
  userBuildsPage,
  userEditProfilePage,
  userPage,
  userResultsPage,
  userVodsPage,
  USER_SEARCH_PAGE,
} from "~/utils/urls";

export const links: LinksFunction = () => {
  return [{ rel: "stylesheet", href: styles }];
};

export const meta: V2_MetaFunction = ({
  data,
}: {
  data: UserPageLoaderData;
}) => {
  if (!data) return [];

  return [{ title: makeTitle(discordFullName(data)) }];
};

export const handle: SendouRouteHandle = {
  i18n: "user",
  breadcrumb: ({ match }) => {
    const data = match.data as UserPageLoaderData | undefined;

    if (!data) return [];

    return [
      {
        imgPath: navIconUrl("u"),
        href: USER_SEARCH_PAGE,
        type: "IMAGE",
      },
      {
        text: data.discordName,
        href: userPage(data),
        type: "TEXT",
      },
    ];
  },
};

export const userParamsSchema = z.object({ identifier: z.string() });

export type UserPageLoaderData = SerializeFrom<typeof loader>;

export const loader = async ({ params, request }: LoaderArgs) => {
  const loggedInUser = await getUserId(request);
  const { identifier } = userParamsSchema.parse(params);
  const user = notFoundIfFalsy(db.users.findByIdentifier(identifier));

  const { playerId, topPlacements } = userTopPlacements(user.id);
  return json({
    id: user.id,
    discordAvatar: user.discordAvatar,
    discordDiscriminator: user.discordDiscriminator,
    discordId: user.discordId,
    discordName: user.discordName,
    twitch: user.twitch,
    twitter: user.twitter,
    youtubeId: user.youtubeId,
    bio: user.bio,
    customUrl: user.customUrl,
    motionSens: user.motionSens,
    stickSens: user.stickSens,
    inGameName: user.inGameName,
    weapons: user.weapons,
    team: user.team,
    country: user.country,
    css: canAddCustomizedColorsToUserProfile(user) ? user.css : undefined,
    badges: db.badges.findByOwnerId(user.id),
    results: db.calendarEvents.findResultsByUserId(user.id),
    buildsCount: db.builds.countByUserId({
      userId: user.id,
      loggedInUserId: loggedInUser?.id,
    }),
    vods: findVods({ userId: user.id }),
    playerId,
    topPlacements,
  });
};

export default function UserPageLayout() {
  const data = useLoaderData<typeof loader>();
  const user = useUser();
  const { t } = useTranslation();

  const isOwnPage = data.id === user?.id;

  useReplaceWithCustomUrl();

  return (
    <Main>
      <SubNav>
        <SubNavLink to={userPage(data)}>{t("header.profile")}</SubNavLink>
        {isOwnPage && (
          <SubNavLink to={userEditProfilePage(data)} prefetch="intent">
            {t("actions.edit")}
          </SubNavLink>
        )}
        {data.results.length > 0 && (
          <SubNavLink to={userResultsPage(data)}>
            {t("results")} ({data.results.length})
          </SubNavLink>
        )}
        {(isOwnPage || data.buildsCount > 0) && (
          <SubNavLink
            to={userBuildsPage(data)}
            prefetch="intent"
            data-testid="builds-tab"
          >
            {t("pages.builds")} ({data.buildsCount})
          </SubNavLink>
        )}
        {data.vods.length > 0 && (
          <SubNavLink to={userVodsPage(data)}>
            {t("pages.vods")} ({data.vods.length})
          </SubNavLink>
        )}
      </SubNav>
      <Outlet />
    </Main>
  );
}

function useReplaceWithCustomUrl() {
  const data = useLoaderData<typeof loader>();
  const location = useLocation();

  React.useEffect(() => {
    if (!data.customUrl) {
      return;
    }

    const identifier = location.pathname.replace("/u/", "").split("/")[0];
    invariant(identifier);

    if (isCustomUrl(identifier)) {
      return;
    }

    window.history.replaceState(
      null,
      "",
      location.pathname
        .split("/")
        .map((part) => (part === identifier ? data.customUrl : part))
        .join("/")
    );
  }, [location, data.customUrl]);
}
