import { GetStaticProps } from "next";
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote";
import React from "react";

import { Bubble } from "@/components/Bubble";
import { DefaultLayout } from "@/components/DefaultLayout";
import { Image } from "@/components/Image";
import { Link } from "@/components/Link";
import { TeamMember } from "@/components/TeamMember";
import { TeamMemberCard } from "@/components/TeamMemberCard";
import { Title } from "@/components/Title";
import {
  getExecs,
  Metadata as TeamMemberData,
  getMemberImagePath,
} from "@/lib/team";

import designData from "../../content/team/design-team.json";
import discordData from "../../content/team/discord-team.json";
import eventsData from "../../content/team/events-team.json";
import externalData from "../../content/team/external-affairs-team.json";
import marketingData from "../../content/team/marketing-team.json";
import photographyData from "../../content/team/photography-team.json";
import repsData from "../../content/team/representatives-team.json";
import systemsData from "../../content/team/systems-committee.json";
import terminalData from "../../content/team/terminal-committee.json";
import webData from "../../content/team/web-committee.json";

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

interface SerializedExec {
  content: MDXRemoteSerializeResult;
  metadata: TeamMemberData;
}

interface Team {
  id: string;
  name: string;
  members: TeamMemberData[];
}

interface Props {
  execs: SerializedExec[];
  teams: Team[];
}

export default function Team({ execs, teams }: Props) {
  return (
    <>
      <Title>Team</Title>
      <DefaultLayout>
        <div className={styles.headerContainer}>
          <div className={styles.headerTextContainer}>
            <h1 className={styles.header}>Meet the Team!</h1>
            <div className={styles.nav}>
              <Link href="#execs">The Executives</Link>
              {teams.map((team) => (
                <Link href={`#${team.id}`} key={team.id}>
                  {team.name}
                </Link>
              ))}
            </div>
            <h2
              className={styles.subheading}
              style={{ borderBottom: "none", margin: 0, padding: 0 }}
            >
              The Executives
            </h2>
          </div>
          <Image src="images/team/team-codey.svg" className={styles.codey} />
        </div>
        <div className={styles.execs} id="execs">
          {execs.map((exec) => {
            return (
              <div key={exec.metadata.name}>
                <TeamMemberCard {...exec.metadata}>
                  <MDXRemote {...exec.content} />
                </TeamMemberCard>
              </div>
            );
          })}
        </div>
        {teams.map((team) => {
          return (
            <div id={team.id} key={team.id}>
              <h2 className={styles.subheading}>{team.name}</h2>
              <MembersList team={team.members} />
            </div>
          );
        })}
      </DefaultLayout>
      <div className={styles.elections}>
        <Bubble>
          <h2 className={styles.electionSubheading}>Elections</h2>
          To find out when and where the next elections will be held, keep an
          eye on on the <Link href="/#news">News</Link>. <br />
          For details on the elections, read our
          <Link href="/about/constitution"> Constitution</Link>.
        </Bubble>
      </div>
    </>
  );
}

Team.Layout = function TeamLayout(props: { children: React.ReactNode }) {
  return <div>{props.children}</div>;
};

interface MembersProps {
  team: TeamMemberData[];
}

function MembersList(props: MembersProps) {
  return (
    <div className={styles.members}>
      {props.team.map((member) => (
        <TeamMember {...member} key={member.name} />
      ))}
    </div>
  );
}

async function getTeamWithImages(team: Team): Promise<Team> {
  return {
    ...team,
    members: await Promise.all(
      team.members.map(async (member) => {
        const image = member.image ?? (await getMemberImagePath(member.name));
        return {
          ...member,
          image,
        };
      })
    ),
  };
}

function memberComparer(a: TeamMemberData, b: TeamMemberData) {
  return a.name.localeCompare(b.name);
}

function sortTeamMembers(team: Team): Team {
  const leads = team.members
    .filter(({ role }) => role === "Team Lead")
    .sort(memberComparer);

  const general = team.members.filter(({ role }) => !role).sort(memberComparer);

  const others = team.members
    .filter(({ role }) => !!role && role !== "Team Lead")
    .sort(memberComparer);

  return { ...team, members: [...leads, ...general, ...others] };
}

export const getStaticProps: GetStaticProps<Props> = async () => {
  const execs = await getExecs();

  // Note that rawTeams do not contain image paths of members, even though
  // TypeScript thinks that it does. It's just to simplify some code.
  const rawTeams = [
    {
      id: "reps",
      name: "Community Representatives",
      members: repsData,
    },
    {
      id: "design",
      name: "Design",
      members: designData,
    },
    {
      id: "discord",
      name: "Discord Bot (CodeyBot) Developers",
      members: discordData,
    },
    {
      id: "events",
      name: "Events",
      members: eventsData,
    },
    {
      id: "external",
      name: "External Affairs",
      members: externalData,
    },
    {
      id: "marketing",
      name: "Marketing",
      members: marketingData,
    },
    {
      id: "photography",
      name: "Photography",
      members: photographyData,
    },
    {
      id: "website",
      name: "Web Committee",
      members: webData,
    },
    {
      id: "system",
      name: "Systems Committee",
      members: systemsData,
    },
    {
      id: "terminal",
      name: "Terminal Committee",
      members: terminalData,
    },
  ] as Team[];

  const teamsWithImages = await Promise.all(rawTeams.map(getTeamWithImages));
  const teamsAfterSorting = teamsWithImages.map(sortTeamMembers);

  return {
    props: {
      execs,
      teams: teamsAfterSorting,
    },
  };
};
