import {
  mdiChartBoxOutline,
  mdiCloseCircleOutline,
  mdiGamepadSquareOutline,
  mdiHistory,
  mdiShieldCheckOutline,
  mdiTimerOutline,
} from '@mdi/js';
import Head from 'next/head';
import React, { ReactElement } from 'react';
import axios from 'axios';
import { useRouter } from 'next/router';
import BaseButton from '../../../components/BaseButton';
import BaseIcon from '../../../components/BaseIcon';
import CardBox from '../../../components/CardBox';
import GuessCard from '../../../components/OsuHigherLower/GuessCard';
import { GameplayRound, GameplaySession } from '../../../components/OsuHigherLower/types';
import SectionMain from '../../../components/SectionMain';
import SectionTitleLineWithButton from '../../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../../config';
import LayoutAuthenticated from '../../../layouts/Authenticated';

const formatModeSelection = (modeSelection: GameplaySession['modeSelection']) => {
  if (modeSelection === 'beatmap_only') {
    return 'Beatmap';
  }

  if (modeSelection === 'mapper_only') {
    return 'Mapper';
  }

  if (modeSelection === 'artist_only') {
    return 'Artist';
  }

  return 'Mixed';
};

const formatSessionDate = (date?: string | null) => {
  if (!date) {
    return 'Still running';
  }

  return new Intl.DateTimeFormat(undefined, {
    month: 'short',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
  }).format(new Date(date));
};

const resultTone = (round: GameplayRound) => {
  if (round.reveal?.loseReason === 'timeout') {
    return 'border-yellow-500/30 bg-yellow-500/10 text-yellow-100';
  }

  return round.reveal?.isCorrect
    ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-100'
    : 'border-red-500/30 bg-red-500/10 text-red-100';
};

export default function SessionDetailPage() {
  const router = useRouter();
  const { sessionId } = router.query;
  const [session, setSession] = React.useState<
    (GameplaySession & {
      leaderboardEntry?: {
        score: number;
        bestStreak: number;
        roundsSurvived: number;
        achievedAt: string;
      } | null;
    }) | null
  >(null);
  const [rounds, setRounds] = React.useState<GameplayRound[]>([]);
  const [isLoading, setIsLoading] = React.useState(true);
  const [errorMessage, setErrorMessage] = React.useState('');

  React.useEffect(() => {
    if (!sessionId || typeof sessionId !== 'string') {
      return;
    }

    let isMounted = true;

    const loadDetail = async () => {
      try {
        setIsLoading(true);
        setErrorMessage('');
        const { data } = await axios.get(`/gameplay/sessions/${sessionId}`);

        if (!isMounted) {
          return;
        }

        setSession(data.session);
        setRounds(Array.isArray(data.rounds) ? data.rounds : []);
      } catch (error: any) {
        if (!isMounted) {
          return;
        }

        setErrorMessage(error?.response?.data || 'Could not load this session.');
      } finally {
        if (isMounted) {
          setIsLoading(false);
        }
      }
    };

    void loadDetail();

    return () => {
      isMounted = false;
    };
  }, [sessionId]);

  return (
    <>
      <Head>
        <title>{getPageTitle('Run detail')}</title>
      </Head>

      <SectionMain>
        <SectionTitleLineWithButton icon={mdiHistory} main title="Run detail">
          <div className="flex flex-wrap items-center gap-3">
            <BaseButton color="whiteDark" href="/play/history" label="Back to history" />
            <BaseButton
              color="info"
              href="/play"
              icon={mdiGamepadSquareOutline}
              label="Open arena"
            />
          </div>
        </SectionTitleLineWithButton>

        {errorMessage ? (
          <div className="mb-6 rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-100">
            {errorMessage}
          </div>
        ) : null}

        {isLoading ? (
          <CardBox className="border border-white/10 bg-[#10141d] text-white">
            <div className="py-10 text-center text-sm text-white/55">
              Loading session detail...
            </div>
          </CardBox>
        ) : null}

        {!isLoading && session ? (
          <div className="space-y-6">
            <CardBox className="border border-white/10 bg-[#10141d] text-white">
              <div className="flex flex-col gap-6 lg:flex-row lg:items-start lg:justify-between">
                <div>
                  <p className="text-sm uppercase tracking-[0.22em] text-white/45">
                    {formatModeSelection(session.modeSelection)} ·{' '}
                    {session.timerProfile === 'insane' ? 'Insane · 5s' : 'Normal · 8s'}
                  </p>
                  <h2 className="mt-2 text-3xl font-semibold text-white">
                    {session.correctGuesses} correct guesses across {session.roundsPlayed} rounds.
                  </h2>
                  <p className="mt-3 text-base leading-7 text-white/65">
                    Started {formatSessionDate(session.startedAt)} · Ended{' '}
                    {formatSessionDate(session.endedAt)}
                  </p>
                </div>

                <div className="grid gap-3 sm:grid-cols-3 lg:w-[460px]">
                  <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                    <div className="flex items-center gap-2">
                      <BaseIcon className="text-white/55" path={mdiShieldCheckOutline} size={16} />
                      <p className="text-[11px] uppercase tracking-[0.16em] text-white/45">
                        Best streak
                      </p>
                    </div>
                    <p className="mt-2 text-2xl font-semibold text-white">
                      {session.bestStreak}
                    </p>
                  </div>
                  <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                    <div className="flex items-center gap-2">
                      <BaseIcon className="text-white/55" path={mdiChartBoxOutline} size={16} />
                      <p className="text-[11px] uppercase tracking-[0.16em] text-white/45">
                        Score
                      </p>
                    </div>
                    <p className="mt-2 text-2xl font-semibold text-white">
                      {session.leaderboardEntry?.score ?? session.correctGuesses}
                    </p>
                  </div>
                  <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                    <div className="flex items-center gap-2">
                      <BaseIcon className="text-white/55" path={mdiTimerOutline} size={16} />
                      <p className="text-[11px] uppercase tracking-[0.16em] text-white/45">
                        Status
                      </p>
                    </div>
                    <p className="mt-2 text-2xl font-semibold capitalize text-white">
                      {session.status}
                    </p>
                  </div>
                </div>
              </div>
            </CardBox>

            {!rounds.length ? (
              <CardBox className="border border-white/10 bg-[#10141d] text-white">
                <div className="py-10 text-center text-sm text-white/55">
                  No rounds were recorded for this session.
                </div>
              </CardBox>
            ) : null}

            {rounds.map((round) => (
              <CardBox className="border border-white/10 bg-[#10141d] text-white" key={round.id}>
                <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
                  <div>
                    <div className="flex flex-wrap items-center gap-2.5">
                      <span className="rounded-full border border-white/10 bg-white/5 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.18em] text-white/60">
                        Round {round.roundNumber}
                      </span>
                      <span className="rounded-full border border-white/10 bg-white/5 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.18em] text-white/60">
                        {round.reveal?.modeLabel}
                      </span>
                      <span
                        className={`rounded-full border px-3 py-1 text-[11px] font-medium uppercase tracking-[0.18em] ${resultTone(round)}`}
                      >
                        {round.reveal?.loseReason === 'timeout'
                          ? 'Timed out'
                          : round.reveal?.isCorrect
                            ? 'Correct'
                            : 'Wrong'}
                      </span>
                    </div>
                    <p className="mt-3 text-sm leading-7 text-white/62">
                      {round.reveal?.loseReason === 'timeout'
                        ? 'The timer expired before an answer reached the server.'
                        : `You chose ${String(round.reveal?.playerChoice).toUpperCase()} and the correct answer was ${String(round.reveal?.correctChoice).toUpperCase()}.`}
                    </p>
                  </div>
                  <div className="rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white/65">
                    Answered {formatSessionDate(round.reveal?.answeredAt || round.presentedAt)}
                  </div>
                </div>

                <div className="mt-5 grid gap-5 lg:grid-cols-2">
                  <GuessCard
                    card={round.cards.a}
                    compact
                    reveal={{
                      show: true,
                      value: round.reveal?.values.a || 0,
                      valueSuffix: round.reveal?.valueSuffix || 'plays',
                      isWinner: round.reveal?.winningChoice === 'a',
                      isWrongSelection:
                        !round.reveal?.isCorrect && round.reveal?.playerChoice === 'a',
                    }}
                    slot="a"
                  />
                  <GuessCard
                    card={round.cards.b}
                    compact
                    reveal={{
                      show: true,
                      value: round.reveal?.values.b || 0,
                      valueSuffix: round.reveal?.valueSuffix || 'plays',
                      isWinner: round.reveal?.winningChoice === 'b',
                      isWrongSelection:
                        !round.reveal?.isCorrect && round.reveal?.playerChoice === 'b',
                    }}
                    slot="b"
                  />
                </div>
              </CardBox>
            ))}
          </div>
        ) : null}

        {!isLoading && !session && !errorMessage ? (
          <CardBox className="border border-white/10 bg-[#10141d] text-white">
            <div className="py-10 text-center text-sm text-white/55">
              This session could not be found.
            </div>
          </CardBox>
        ) : null}
      </SectionMain>
    </>
  );
}

SessionDetailPage.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated permission="READ_GAME_SESSIONS">{page}</LayoutAuthenticated>;
};
