<script lang="ts">
import type { Media } from "$lib/Data/AniList/media";
import ParallaxImage from "$lib/Image/ParallaxImage.svelte";
import { outboundLink } from "$lib/Media/links";
import settings from "$stores/settings";
import locale from "$stores/locale";
import { mediaTitle } from "./mediaTitle";
import { track } from "$lib/analytics";

interface Props {
	media: Media[];
	type: "anime" | "manga";
	onClose: () => void;
	spinDuration?: number;
}

let { media, type, onClose, spinDuration = 2 }: Props = $props();
let isSpinning = $state(false);
let selectedIndex = $state(0);
let displayIndex = $state(0);
let spinTimeout: ReturnType<typeof setTimeout> | null = $state(null);
let showResult = $state(false);
let isClosing = $state(false);
let currentMedia = $derived(media[displayIndex]);

const startRoulette = () => {
	if (media.length === 0 || isSpinning) return;

	track("Spin Roulette", { type });

	isSpinning = true;
	showResult = false;
	selectedIndex = Math.floor(Math.random() * media.length);

	const startTime = Date.now();
	const durationMs = spinDuration * 1000;
	const minSpeed = 50;
	const maxSpeed = 350;
	const slowdownStart = 0.8;

	const spin = () => {
		displayIndex = (displayIndex + 1) % media.length;

		const elapsed = Date.now() - startTime;
		const progress = Math.min(elapsed / durationMs, 1);
		let speed = minSpeed;

		if (progress > slowdownStart) {
			const slowdownProgress = (progress - slowdownStart) / (1 - slowdownStart);

			speed = minSpeed + slowdownProgress * (maxSpeed - minSpeed);
		}

		if (progress >= 1) {
			displayIndex = selectedIndex;
			spinTimeout = null;
			isSpinning = false;
			showResult = true;

			return;
		}

		spinTimeout = setTimeout(spin, speed);
	};

	spinTimeout = setTimeout(spin, minSpeed);
};

const handleClose = () => {
	if (isClosing) return;

	if (spinTimeout) {
		clearTimeout(spinTimeout);

		spinTimeout = null;
	}

	isSpinning = false;
	showResult = false;
	isClosing = true;

	setTimeout(() => onClose(), 200);
};

const handleOverlayClick = (e: MouseEvent) => {
	if (e.target === e.currentTarget) handleClose();
};
</script>

<svelte:window onkeydown={(e) => e.key === 'Escape' && handleClose()} />

<div
  class="roulette-overlay {isClosing ? 'fade-out' : 'fade-in'}"
  role="dialog"
  aria-modal="true"
  tabindex="-1"
  onclick={handleOverlayClick}
  onkeydown={() => {
    /* */
  }}
>
  <div class="roulette-container card {isClosing ? 'fade-out' : 'fade-in'}">
    <button class="close-button" onclick={handleClose} aria-label={$locale().lists.roulette?.closeAriaLabel}
      >&times;</button
    >

    <h3 class="roulette-title">
      {type === 'anime' ? $locale().lists.roulette?.watchTitle : $locale().lists.roulette?.readTitle}
    </h3>

    {#if media.length === 0}
      <p>{$locale().lists.roulette?.noMedia}</p>
    {:else}
      <div class="roulette-display" class:spinning={isSpinning} class:result={showResult}>
        {#if currentMedia}
          <div class="media-card">
            <div class="cover-wrapper">
              <ParallaxImage
                source={$settings.displayDataSaver
                  ? currentMedia.coverImage.medium
                  : currentMedia.coverImage.extraLarge}
                alternativeText="Cover"
                limit={5}
                classList={`roulette-cover${
                  currentMedia.isAdult && $settings.displayBlurAdultContent ? ' adult' : ''
                }`}
              />
            </div>
            <div class="media-info">
              <span class="media-title-text">{mediaTitle(currentMedia)}</span>

              {#if showResult}
                <a
                  href={outboundLink(currentMedia, type, $settings.displayOutboundLinksTo)}
                  target="_blank"
                  class="view-link"
                  data-umami-event="Roulette View Media"
                >
                  {$locale({
                    values: {
                      site:
                        $settings.displayOutboundLinksTo === 'anilist'
                          ? 'AniList'
                          : $settings.displayOutboundLinksTo === 'livechartme'
                            ? 'LiveChart.me'
                            : $settings.displayOutboundLinksTo === 'animeschedule'
                              ? 'AnimeSchedule'
                              : 'MyAnimeList'
                    }
                  }).lists.roulette?.viewOn}
                </a>
              {/if}
            </div>
          </div>
        {/if}
      </div>

      <div class="roulette-actions">
        {#if !isSpinning && !showResult}
          <button onclick={startRoulette}>{$locale().lists.roulette?.spin}</button>
        {:else if showResult}
          <button onclick={startRoulette}>{$locale().lists.roulette?.spinAgain}</button>
        {:else}
          <button disabled>{$locale().lists.roulette?.spinning}</button>
        {/if}
      </div>
    {/if}
  </div>
</div>

<style>
  .roulette-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--scrim);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    opacity: 0;
  }

  .roulette-overlay.fade-in {
    animation: overlayFadeIn 0.15s ease-in-out forwards;
  }

  .roulette-overlay.fade-out {
    animation: overlayFadeOut 0.2s ease-in-out forwards;
  }

  @keyframes overlayFadeIn {
    from {
      opacity: 0;
      backdrop-filter: blur(0px);
    }

    to {
      opacity: 1;
      backdrop-filter: blur(3px);
    }
  }

  @keyframes overlayFadeOut {
    from {
      opacity: 1;
      backdrop-filter: blur(3px);
    }

    to {
      opacity: 0;
      backdrop-filter: blur(0px);
    }
  }

  .roulette-container {
    max-width: 400px;
    width: 90%;
    position: relative;
    opacity: 0;
    transform: translateY(-10px);
  }

  .roulette-container.fade-in {
    animation: containerFadeIn 0.2s ease-in-out forwards;
  }

  .roulette-container.fade-out {
    animation: containerFadeOut 0.2s ease-in-out forwards;
  }

  @keyframes containerFadeIn {
    from {
      opacity: 0;
      transform: translateY(-10px);
    }

    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  @keyframes containerFadeOut {
    from {
      opacity: 1;
      transform: translateY(0);
    }

    to {
      opacity: 0;
      transform: translateY(-10px);
    }
  }

  .close-button {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    background: transparent;
    box-shadow: none;
    color: var(--base04);
    font-size: 1.5rem;
    padding: 0.25rem 0.5rem;
    line-height: 1;
  }

  .close-button:hover {
    background: transparent;
    color: var(--base05);
  }

  .roulette-title {
    text-align: center;
    margin: 0 0 1rem;
    font-size: 1.25rem;
    color: var(--base05);
  }

  .roulette-display {
    min-height: 280px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.5rem;
  }

  .roulette-display.spinning .media-card {
    animation: pulse 0.15s ease-in-out infinite;
  }

  .roulette-display.result .media-card {
    animation: celebrate 0.5s ease-out;
  }

  @keyframes pulse {
    0%,
    100% {
      transform: scale(1);
    }

    50% {
      transform: scale(1.02);
    }
  }

  @keyframes celebrate {
    0% {
      transform: scale(1.1);
    }

    50% {
      transform: scale(1.05);
    }

    100% {
      transform: scale(1);
    }
  }

  .media-card {
    text-align: center;
  }

  .cover-wrapper {
    width: 150px;
    height: 220px;
    margin: 0 auto 1rem;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: var(--shadow-card);
  }

  .cover-wrapper :global(.roulette-cover) {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .cover-wrapper :global(.adult) {
    filter: blur(8px);
  }

  .media-info {
    display: flex;
    flex-direction: column;
  }

  .media-title-text {
    font-weight: 500;
    color: var(--base05);
    font-size: 1rem;
    max-width: 280px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
    margin: 0 auto;
  }

  .view-link {
    color: var(--base0D);
    text-decoration: none;
    font-size: 0.875rem;
  }

  .view-link:hover {
    color: var(--base0C);
    text-decoration: underline;
  }

  .roulette-actions {
    display: flex;
    justify-content: center;
  }
</style>
