<script lang="ts">
  import { bibleBooks, type BibleBook } from "$lib/types/bible";

  import type { PageProps } from "./$types";
  import { browser } from "$app/environment";

  import VerseDisplay from "$lib/components/VerseDisplay.svelte";
  import SearchInput from "$lib/components/SearchInput.svelte";
  import GuessesTable from "$lib/components/GuessesTable.svelte";
  import CountdownTimer from "$lib/components/CountdownTimer.svelte";
  import WinScreen from "$lib/components/WinScreen.svelte";
  import Feedback from "$lib/components/Feedback.svelte";
  import TitleAnimation from "$lib/components/TitleAnimation.svelte";
  import { getGrade } from "$lib/utils/game";

  interface Guess {
    book: BibleBook;
    testamentMatch: boolean;
    sectionMatch: boolean;
    adjacent: boolean;
  }

  let { data }: PageProps = $props();

  let dailyVerse = $derived(data.dailyVerse);
  let correctBookId = $derived(data.correctBookId);

  let guesses = $state<Guess[]>([]);

  let searchQuery = $state("");

  let copied = $state(false);
  let isDev = $state(false);

  let anonymousId = $state("");
  let statsSubmitted = $state(false);
  let statsData = $state<{
    solveRank: number;
    guessRank: number;
    totalSolves: number;
    averageGuesses: number;
  } | null>(null);

  let guessedIds = $derived(new Set(guesses.map((g) => g.book.id)));

  const currentDate = $derived(
    new Date().toLocaleDateString("en-US", {
      weekday: "long",
      year: "numeric",
      month: "long",
      day: "numeric",
    })
  );

  let isWon = $derived(guesses.some((g) => g.book.id === correctBookId));
  let grade = $derived(
    isWon
      ? getGrade(guesses.length, getBookById(correctBookId)?.popularity ?? 0)
      : ""
  );

  function getBookById(id: string): BibleBook | undefined {
    return bibleBooks.find((b) => b.id === id);
  }

  function isAdjacent(id1: string, id2: string): boolean {
    const b1 = getBookById(id1);
    const b2 = getBookById(id2);
    return !!(b1 && b2 && Math.abs(b1.order - b2.order) === 1);
  }

  function submitGuess(bookId: string) {
    if (guesses.some((g) => g.book.id === bookId)) return;

    const book = getBookById(bookId);
    if (!book) return;

    const correctBook = getBookById(correctBookId);
    if (!correctBook) return;

    const testamentMatch = book.testament === correctBook.testament;
    const sectionMatch = book.section === correctBook.section;
    const adjacent = isAdjacent(book.id, correctBookId);

    console.log(
      `Guess: ${book.name} (order ${book.order}), Correct: ${correctBook.name} (order ${correctBook.order}), Adjacent: ${adjacent}`
    );

    guesses = [
      {
        book,
        testamentMatch,
        sectionMatch,
        adjacent,
      },
      ...guesses,
    ];

    searchQuery = "";
  }

  function generateUUID(): string {
    // Try native randomUUID if available
    if (typeof window.crypto.randomUUID === "function") {
      return window.crypto.randomUUID();
    }

    // Fallback UUID v4 generator for older browsers
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
      const r = window.crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0;
      const v = c === "x" ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }

  function getOrCreateAnonymousId(): string {
    if (!browser) return "";
    const key = "bibdle-anonymous-id";
    let id = localStorage.getItem(key);
    if (!id) {
      id = generateUUID();
      localStorage.setItem(key, id);
    }
    return id;
  }

  // Initialize anonymous ID
  $effect(() => {
    if (!browser) return;
    anonymousId = getOrCreateAnonymousId();
    const statsKey = `bibdle-stats-submitted-${dailyVerse.date}`;
    statsSubmitted = localStorage.getItem(statsKey) === "true";
  });

  $effect(() => {
    if (!browser) return;
    isDev = window.location.host === "localhost:5173";
  });

  // Load saved guesses
  $effect(() => {
    if (!browser) return;

    const key = `bibdle-guesses-${dailyVerse.date}`;
    const saved = localStorage.getItem(key);
    if (saved) {
      let savedIds: string[] = JSON.parse(saved);
      savedIds = Array.from(new Set(savedIds));
      guesses = savedIds.map((bookId: string) => {
        const book = getBookById(bookId)!;
        const correctBook = getBookById(correctBookId)!;
        const testamentMatch = book.testament === correctBook.testament;
        const sectionMatch = book.section === correctBook.section;
        const adjacent = isAdjacent(bookId, correctBookId);
        return {
          book,
          testamentMatch,
          sectionMatch,
          adjacent,
        };
      });
    }
  });

  $effect(() => {
    if (!browser) return;
    localStorage.setItem(
      `bibdle-guesses-${dailyVerse.date}`,
      JSON.stringify(guesses.map((g) => g.book.id))
    );
  });

  // Auto-submit stats when user wins
  $effect(() => {
    console.log("Stats effect triggered:", {
      browser,
      isWon,
      anonymousId,
      statsSubmitted,
      statsData,
    });

    if (!browser || !isWon || !anonymousId) {
      console.log("Basic conditions not met");
      return;
    }

    if (statsSubmitted && !statsData) {
      console.log("Fetching existing stats...");

      (async () => {
        try {
          const response = await fetch(
            `/api/submit-completion?anonymousId=${anonymousId}&date=${dailyVerse.date}`
          );
          const result = await response.json();
          console.log("Stats response:", result);

          if (result.success && result.stats) {
            console.log("Setting stats data:", result.stats);
            statsData = result.stats;
            localStorage.setItem(
              `bibdle-stats-submitted-${dailyVerse.date}`,
              "true"
            );
          } else if (result.error) {
            console.error("Server error:", result.error);
          } else {
            console.error("Unexpected response format:", result);
          }
        } catch (err) {
          console.error("Stats fetch failed:", err);
        }
      })();

      return;
    }

    console.log("Submitting stats...");

    async function submitStats() {
      try {
        const payload = {
          anonymousId,
          date: dailyVerse.date,
          guessCount: guesses.length,
        };

        console.log("Sending POST request with:", payload);

        const response = await fetch("/api/submit-completion", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(payload),
        });

        const result = await response.json();
        console.log("Stats response:", result);

        if (result.success && result.stats) {
          console.log("Setting stats data:", result.stats);
          statsData = result.stats;
          statsSubmitted = true;
          localStorage.setItem(
            `bibdle-stats-submitted-${dailyVerse.date}`,
            "true"
          );
        } else if (result.error) {
          console.error("Server error:", result.error);
        } else {
          console.error("Unexpected response format:", result);
        }
      } catch (err) {
        console.error("Stats submission failed:", err);
      }
    }

    submitStats();
  });

  function generateShareText(): string {
    const emojis = guesses
      .slice()
      .reverse()
      .map((guess) => {
        if (guess.book.id === correctBookId) return "✅";
        if (guess.adjacent) return "‼️";
        if (guess.sectionMatch) return "🟩";
        if (guess.testamentMatch) return "🟧";
        return "🟥";
      })
      .join("");

    const dateFormatter = new Intl.DateTimeFormat("en-US", {
      month: "short",
      day: "numeric",
      year: "numeric",
    });
    const formattedDate = dateFormatter.format(
      new Date(`${dailyVerse.date}T00:00:00`)
    );
    const siteUrl = window.location.origin;
    return [
      `📖 Bibdle | ${formattedDate} 📖`,
      `${grade} (${guesses.length} guesses)`,
      `${emojis}\n`,
      siteUrl,
    ].join("\n");
  }

  async function share() {
    if (!browser) return;

    const shareText = generateShareText();

    try {
      if ("share" in navigator) {
        await (navigator as any).share({ text: shareText });
      } else {
        await (navigator as any).clipboard.writeText(shareText);
      }
    } catch (err) {
      console.error("Share failed:", err);
      throw err;
    }
  }

  async function copyToClipboard() {
    if (!browser) return;

    const shareText = generateShareText();

    try {
      await (navigator as any).clipboard.writeText(shareText);
      copied = true;
      setTimeout(() => {
        copied = false;
      }, 5000);
    } catch (err) {
      console.error("Copy to clipboard failed:", err);
      throw err;
    }
  }

  function handleShare() {
    if (copied || !browser) return;
    const useClipboard = !("share" in navigator);
    if (useClipboard) {
      copied = true;
    }
    share()
      .then(() => {
        if (useClipboard) {
          setTimeout(() => {
            copied = false;
          }, 5000);
        }
      })
      .catch(() => {
        if (useClipboard) {
          copied = false;
        }
      });
  }

  function clearLocalStorage() {
    if (!browser) return;
    // Clear all bibdle-related localStorage items
    const keysToRemove: string[] = [];
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (key && key.startsWith("bibdle-")) {
        keysToRemove.push(key);
      }
    }
    keysToRemove.forEach((key) => localStorage.removeItem(key));
    // Reload the page to reset state
    window.location.reload();
  }
</script>

<svelte:head>
  <title>Bibdle &mdash; A daily bible game{isDev ? " (dev)" : ""}</title>
  <meta
    name="description"
    content="A Wordle-inspired Bible game (short for Bible Daily)"
  />
</svelte:head>

<div class="min-h-dvh md:bg-linear-to-br md:from-blue-50 md:to-indigo-200 py-8">
  <div class="w-full max-w-3xl mx-auto px-4">
    <h1
      class="text-3xl md:text-4xl font-bold text-center uppercase text-gray-600 drop-shadow-2xl tracking-widest p-4 sm:p-8"
    >
      <TitleAnimation />
      <div class="font-normal">{false ? "dev" : ""}</div>
    </h1>
    <div class="text-center mb-8">
      <span class="big-text">{currentDate}</span>
    </div>

    <VerseDisplay {data} {isWon} />

    {#if !isWon}
      <SearchInput bind:searchQuery {guessedIds} {submitGuess} />
    {:else}
      <WinScreen
        {grade}
        {statsData}
        {correctBookId}
        {handleShare}
        {copyToClipboard}
        bind:copied
        {statsSubmitted}
        guessCount={guesses.length}
      />
      <CountdownTimer />
    {/if}

    <GuessesTable {guesses} {correctBookId} />
    {#if isWon}
      <Feedback />
    {/if}
    {#if isDev}
      <button
        onclick={clearLocalStorage}
        class="mt-4 px-4 py-2 bg-red-500 hover:bg-red-600 text-white rounded-lg text-sm font-bold transition-colors"
      >
        Clear LocalStorage
      </button>
    {/if}
  </div>
</div>
