<script lang="ts">
  import "$lib/style.css";
  import "iconify-icon";
  import { hasSeed, passwordRequest } from "$lib/wallet.svelte";
  import { onMount } from "svelte";
  import { goto } from "$app/navigation";
  import PasswordDialog from "$lib/components/PasswordDialog.svelte";
  import { page } from "$app/stores";
  import { start as startNwc } from "$lib/nwc.svelte";
  import SplashScreen from "$lib/components/SplashScreen.svelte";
  import ErrorDialog from "$lib/components/ErrorDialog.svelte";
  import InstallPrompt from "$lib/components/InstallPrompt.svelte";

  type AppError = {
    message: string;
    stack?: string;
  };

  let passwordDialogOpen = $state(false);
  let showSplash = $state(true);
  let currentError = $state<AppError | null>(null);
  let showInstallPrompt = $state(false);
  let deferredPrompt: Event | undefined = $state(undefined);

  async function handleInstallClick() {
    if (deferredPrompt) {
      (deferredPrompt as any).prompt();
      const { outcome } = await (deferredPrompt as any).userChoice;
      if (outcome === "accepted") {
        deferredPrompt = undefined;
        showInstallPrompt = false;
      }
    }
  }

  function handleUnlockAttempt(pw: string) {
    if (passwordRequest.resolve) {
      passwordRequest.resolve(pw);
      passwordRequest.resolve = undefined;
      passwordRequest.reject = undefined;
      passwordRequest.pending = false;
      startNwc();
    }
    passwordDialogOpen = false;
  }

  function goToSettings() {
    goto("/settings");
  }

  const { children } = $props();

  $effect(() => {
    if (passwordRequest.pending && !passwordDialogOpen) {
      passwordDialogOpen = true;
    }
  });

  const isOnSetup = $derived($page.route.id?.startsWith("/setup"));
  const isOnSettings = $derived($page.route.id?.startsWith("/settings"));
  const showSettingsButton = $derived(!isOnSetup && !isOnSettings && hasSeed());

  onMount(() => {
    setTimeout(() => {
      showSplash = false;
    }, 3000);

    window.addEventListener("error", (event: ErrorEvent) => {
      event.preventDefault();
      if (event.message.indexOf("Svelte error")) return;
      currentError = { message: event.message, stack: event.error?.stack };
    });

    window.addEventListener(
      "unhandledrejection",
      (event: PromiseRejectionEvent) => {
        const reason = event.reason;
        if (reason instanceof Error) {
          if (reason.message.indexOf("Svelte error")) return;
          currentError = { message: reason.message, stack: reason.stack };
        } else {
          if (String(reason).indexOf("Svelte error")) return;
          currentError = { message: String(reason) };
        }
      }
    );

    window.addEventListener("beforeinstallprompt", (e) => {
      e.preventDefault();
      deferredPrompt = e;
      if (
        !window.matchMedia("(display-mode: standalone)").matches &&
        /Mobi|Android/i.test(navigator.userAgent)
      ) {
        showInstallPrompt = true;
      }
    });

    if (!hasSeed() && !isOnSetup) {
      goto("/setup");
    }
  });
</script>

{#if showInstallPrompt && deferredPrompt}
  <InstallPrompt onInstall={handleInstallClick} />
{:else if showSplash}
  <SplashScreen />
{:else}
  <main class="app-wrapper">
    {#if showSettingsButton}
      <div class="settings-button-container">
        <button class="retro-btn settings-btn" onclick={goToSettings}>
          <iconify-icon icon="mdi:cog" width="16" height="16"></iconify-icon>
          Settings
        </button>
      </div>
    {/if}

    {#if !isOnSetup || !passwordRequest.pending}
      {@render children()}
    {/if}
  </main>

  <PasswordDialog bind:open={passwordDialogOpen} unlock={handleUnlockAttempt} />
{/if}

<ErrorDialog error={currentError} onclose={() => (currentError = null)} />

<style>
  .settings-button-container {
    position: absolute;
    top: 1rem;
    right: 1rem;
    z-index: 10;
  }

  .settings-btn {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.7rem;
    padding: 0.5rem 0.75rem;
  }
</style>
