import {
  mdiChartBoxOutline,
  mdiGamepadSquareOutline,
  mdiHistory,
  mdiPlayCircleOutline,
  mdiShieldCheckOutline,
  mdiTimerOutline,
} from '@mdi/js';
import Head from 'next/head';
import Link from 'next/link';
import React, { ReactElement } from 'react';
import axios from 'axios';
import BaseButton from '../../components/BaseButton';
import BaseIcon from '../../components/BaseIcon';
import CardBox from '../../components/CardBox';
import {
  GameplayLeaderboardEntry,
  HistorySession,
} 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: HistorySession['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 statusTone: Record<HistorySession['status'], string> = {
  active: 'border-emerald-500/30 bg-emerald-500/10 text-emerald-100',
  finished: 'border-white/10 bg-white/5 text-white/70',
  abandoned: 'border-yellow-500/30 bg-yellow-500/10 text-yellow-100',
};

export default function PlayHistoryPage() {
  const [sessions, setSessions] = React.useState<HistorySession[]>([]);
  const [leaderboard, setLeaderboard] = React.useState<GameplayLeaderboardEntry[]>([]);
  const [isLoading, setIsLoading] = React.useState(true);
  const [errorMessage, setErrorMessage] = React.useState('');

  React.useEffect(() => {
    let isMounted = true;

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

        if (!isMounted) {
          return;
        }

        setSessions(Array.isArray(data?.sessions) ? data.sessions : []);
        setLeaderboard(Array.isArray(data?.leaderboard) ? data.leaderboard : []);
      } catch (error: any) {
        if (!isMounted) {
          return;
        }

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

    void loadHistory();

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

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

      <SectionMain>
        <SectionTitleLineWithButton icon={mdiHistory} main title="Run history">
          <div className="flex items-center gap-3">
            <BaseButton
              color="info"
              href="/play"
              icon={mdiPlayCircleOutline}
              label="Back to play"
            />
          </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}

        <div className="grid gap-6 xl:grid-cols-[1.65fr_1fr]">
          <CardBox className="border border-white/10 bg-[#10141d] text-white">
            <div className="flex items-center justify-between gap-3">
              <div>
                <p className="text-sm uppercase tracking-[0.22em] text-white/45">
                  Your recent sessions
                </p>
                <p className="mt-2 text-2xl font-semibold text-white">
                  Review finished runs or resume the active one.
                </p>
              </div>
            </div>

            <div className="mt-6 space-y-4">
              {isLoading ? (
                <div className="rounded-2xl border border-white/10 bg-white/[0.03] px-4 py-8 text-center text-sm text-white/55">
                  Loading your sessions...
                </div>
              ) : null}

              {!isLoading && !sessions.length ? (
                <div className="rounded-2xl border border-dashed border-white/10 bg-white/[0.03] px-4 py-10 text-center text-white/55">
                  You have not started a run yet. Head back to the arena and launch your
                  first session.
                </div>
              ) : null}

              {!isLoading
                ? sessions.map((session) => (
                    <Link
                      className="block rounded-[28px] border border-white/10 bg-white/5 px-5 py-5 transition hover:border-white/20"
                      href={
                        session.status === 'active'
                          ? '/play'
                          : `/play/sessions/${session.id}`
                      }
                      key={session.id}
                    >
                      <div className="flex flex-col gap-5 lg:flex-row lg:items-center lg:justify-between">
                        <div className="space-y-4">
                          <div className="flex flex-wrap items-center gap-2.5">
                            <span
                              className={`rounded-full border px-3 py-1 text-[11px] font-medium uppercase tracking-[0.18em] ${statusTone[session.status]}`}
                            >
                              {session.status === 'active' ? 'In progress' : session.status}
                            </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">
                              {formatModeSelection(session.modeSelection)}
                            </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">
                              {session.timerProfile === 'insane' ? 'Insane · 5s' : 'Normal · 8s'}
                            </span>
                          </div>

                          <div>
                            <p className="text-2xl font-semibold text-white">
                              {session.correctGuesses} correct guesses
                            </p>
                            <p className="mt-2 text-sm text-white/55">
                              {formatSessionDate(session.endedAt || session.startedAt)}
                            </p>
                          </div>
                        </div>

                        <div className="grid gap-3 sm:grid-cols-3 lg:w-[390px]">
                          <div className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3">
                            <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-xl font-semibold text-white">
                              {session.bestStreak}
                            </p>
                          </div>

                          <div className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3">
                            <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">
                                Rounds played
                              </p>
                            </div>
                            <p className="mt-2 text-xl font-semibold text-white">
                              {session.roundsPlayed}
                            </p>
                          </div>

                          <div className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3">
                            <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-xl font-semibold text-white">
                              {session.leaderboardEntry?.score ?? session.correctGuesses}
                            </p>
                          </div>
                        </div>
                      </div>
                    </Link>
                  ))
                : null}
            </div>
          </CardBox>

          <div className="space-y-6">
            <CardBox className="border border-white/10 bg-[#10141d] text-white">
              <p className="text-sm uppercase tracking-[0.22em] text-white/45">
                Top all-time scores
              </p>
              <div className="mt-5 space-y-3">
                {leaderboard.length ? (
                  leaderboard.map((entry, index) => (
                    <div
                      className="rounded-2xl border border-white/10 bg-white/5 px-4 py-4"
                      key={entry.id}
                    >
                      <div className="flex items-start justify-between gap-3">
                        <div>
                          <p className="text-sm text-white/55">#{index + 1}</p>
                          <p className="mt-1 text-base font-medium text-white">
                            {entry.user.name}
                          </p>
                          <p className="mt-2 text-sm text-white/45">
                            {formatSessionDate(entry.achievedAt)}
                          </p>
                        </div>
                        <div className="text-right">
                          <p className="text-2xl font-semibold text-white">{entry.score}</p>
                          <p className="text-xs uppercase tracking-[0.16em] text-white/45">
                            correct
                          </p>
                        </div>
                      </div>
                    </div>
                  ))
                ) : (
                  <div className="rounded-2xl border border-dashed border-white/10 bg-white/[0.03] px-4 py-6 text-sm text-white/55">
                    No leaderboard entries yet.
                  </div>
                )}
              </div>
            </CardBox>

            <CardBox className="border border-white/10 bg-[#10141d] text-white">
              <p className="text-sm uppercase tracking-[0.22em] text-white/45">
                Need another run?
              </p>
              <p className="mt-3 text-base leading-7 text-white/65">
                Start a fresh session from the play screen. Active runs are preserved on the
                server until you finish or replace them.
              </p>
              <div className="mt-6 flex flex-wrap gap-3">
                <BaseButton
                  color="info"
                  href="/play"
                  icon={mdiGamepadSquareOutline}
                  label="Open arena"
                />
              </div>
            </CardBox>
          </div>
        </div>
      </SectionMain>
    </>
  );
}

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