<script lang="ts">
  import { browser } from '$app/environment';
  import { page } from '$app/stores';
  import { ACDBBirthdays, type ACDBBirthday } from '$lib/Data/Birthday/secondary';
  import { aniSearchBirthdays, type aniSearchBirthday } from '$lib/Data/Birthday/primary';
  import Error from '$lib/Error/RateLimited.svelte';
  import { onMount } from 'svelte';
  import { clearAllParameters, parseOrDefault } from '../Utility/parameters';
  import Skeleton from '$lib/Loading/Skeleton.svelte';
  import Message from '$lib/Loading/Message.svelte';
  import tooltip from '$lib/Tooltip/tooltip';

  interface Birthday {
    name: string;
    image: string;
    origin?: string;
  }

  const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
  let date = new Date();
  let month = parseOrDefault(urlParameters, 'month', date.getMonth() + 1);
  let day = parseOrDefault(urlParameters, 'day', date.getDate());
  let anisearchBirthdays: Promise<aniSearchBirthday[]>;
  let acdbBirthdays: Promise<ACDBBirthday[]>;

  $: {
    month = Math.min(month, 12);
    month = Math.max(month, 1);
    day = Math.min(day, new Date(new Date().getFullYear(), month, 0).getDate());
    day = Math.max(day, 1);

    if (browser) anisearchBirthdays = aniSearchBirthdays(month, day);

    acdbBirthdays = ACDBBirthdays(month, day);

    if (browser) {
      $page.url.searchParams.set('month', month.toString());
      $page.url.searchParams.set('day', day.toString());
      clearAllParameters(['month', 'day']);
      history.replaceState(null, '', `?${$page.url.searchParams.toString()}`);
    }
  }

  onMount(() => clearAllParameters(['month', 'day']));

  const normaliseName = (name: string): string => name.toLowerCase().split(' ').sort().join(' ');

  const fixName = (name: string): string => {
    const split = name.split(' ');
    const last = split[split.length - 1];

    if (last === last.toUpperCase()) {
      split[split.length - 1] = last[0] + last.slice(1).toLowerCase();
      return split.join(' ');
    }

    const bracketIndex = name.indexOf('[');

    if (bracketIndex !== -1) return name.slice(0, bracketIndex).trim();

    return name;
  };

  const combineBirthdaySources = (
    acdb: ACDBBirthday[],
    aniSearch: aniSearchBirthday[]
  ): Birthday[] => {
    const nameMap = new Map<string, Birthday>();

    for (const entry of aniSearch.map((entry) => ({
      ...entry,
      normalisedName: normaliseName(fixName(entry.name))
    }))) {
      if (!nameMap.has(entry.normalisedName))
        nameMap.set(entry.normalisedName, {
          name: fixName(entry.name),
          image: entry.image
        });
    }

    for (const entry of acdb) {
      const normalisedName = normaliseName(fixName(entry.name));

      if (!nameMap.has(normalisedName))
        nameMap.set(normalisedName, {
          name: entry.name,
          image: entry.character_image,
          origin: entry.origin
        });
    }

    return Array.from(nameMap.values());
  };
</script>

{#await acdbBirthdays}
  <Message message="Loading birthday set one ..." />

  <Skeleton grid={true} count={100} width="150px" height="170px" />
{:then acdbBirthdays}
  {#await anisearchBirthdays}
    <Message message="Loading birthday set two ..." />

    <Skeleton grid={true} count={100} width="150px" height="170px" />
  {:then anisearch}
    {@const birthdays = combineBirthdaySources(acdbBirthdays, anisearch)}

    <p>
      <select bind:value={month}>
        {#each Array.from({ length: 12 }, (_, i) => i + 1) as month}
          <option value={month}>
            {new Date(0, month - 1).toLocaleString('default', { month: 'long' })}
          </option>
        {/each}
      </select>

      <select bind:value={day}>
        {#each Array.from({ length: new Date(new Date().getFullYear(), month, 0).getDate() }, (_, i) => i + 1) as day}
          <option value={day}>{day}</option>
        {/each}
      </select>
    </p>

    <div class="characters">
      {#each birthdays as birthday}
        <div class="card card-small">
          <a
            href={`https://anilist.co/search/characters?search=${encodeURIComponent(
              birthday.name
            ).replace(/%20/g, '+')}`}
            target="_blank"
            title={birthday.origin}
            use:tooltip
            data-tooltip-disable={birthday.origin === undefined}
          >
            {birthday.name}
            <img src={birthday.image} alt="Character (Large)" class="character-image" />
          </a>
        </div>
      {/each}
    </div>
  {:catch}
    <Error type="Character" card />
  {/await}
{:catch}
  <Error type="Character" card />
{/await}

<style lang="scss">
  .characters {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 1rem;
    grid-row-gap: 1rem;
    align-items: start;

    img {
      width: 100%;
      height: auto;
      object-fit: cover;
      border-radius: 8px;
      margin-top: 0.5rem;
      box-shadow: 0 4px 30px var(--base01);
    }
  }
</style>
