<script lang="ts">
  import { getBuildInfo, getAppVersion } from '../utils/tauri-bridge';
  import { checkForUpdates, downloadAndInstall } from '../utils/updater-bridge';
  import { isTauri, isTauriDesktop } from '../utils/platform.js';
  import { openExternalUrl } from '../utils/external-links.js';
  import { Button } from '$lib/components/ui/button';
  import X from '@lucide/svelte/icons/x';
  import ExternalLink from '@lucide/svelte/icons/external-link';
  import Download from '@lucide/svelte/icons/download';

  const openExternal = async (url: string) => {
    try {
      await openExternalUrl(url, {
        log: () => {},
      });
    } catch {
      // Ignore opener failures to avoid noisy console warnings from unsupported environments.
    }
  };

  interface Props {
    open?: boolean;
    onClose?: () => void;
  }

  let { open = $bindable(false), onClose }: Props = $props();

  const fallbackVersion =
    import.meta.env.VITE_PKG_VERSION || import.meta.env.VITE_APP_VERSION || '';

  let version = $state(fallbackVersion);
  let buildDate = $state('');
  let arch = $state('');
  let os = $state('');
  let license = $state('BUSL-1.1');
  let updateStatus = $state('');
  let loaded = $state(false);
  let loading = $state(false);
  let loadSequence = 0;
  let availableUpdate: {
    available?: boolean;
    version?: string;
    body?: string;
    _update?: unknown;
  } | null = $state(null);
  let installing = $state(false);
  let installProgress = $state(0);
  let installError = $state('');

  const osLabels: Record<string, string> = {
    macos: 'macOS',
    windows: 'Windows',
    linux: 'Linux',
  };

  // "Apple Silicon" / "Intel (x64)" only make sense on macOS; Snapdragon
  // Windows laptops also report `aarch64`, and x64 Windows/Linux boxes aren't
  // always Intel.
  const archLabel = (osName: string, archName: string): string => {
    const a = (archName || '').toLowerCase();
    const o = (osName || '').toLowerCase();
    if (a === 'aarch64' || a === 'arm64') {
      return o === 'macos' ? 'Apple Silicon' : 'ARM64';
    }
    if (a === 'x86_64' || a === 'x64') {
      return o === 'macos' ? 'Intel (x64)' : 'x64';
    }
    if (a === 'x86') return 'x86';
    return archName;
  };

  const loadAboutInfo = async (): Promise<void> => {
    const sequence = ++loadSequence;
    loading = true;
    loaded = false;
    updateStatus = isTauri ? 'Checking...' : version ? `Web build (v${version})` : 'Web build';

    if (isTauri) {
      try {
        const info = await getBuildInfo();
        if (sequence !== loadSequence) return;
        if (info) {
          version = info.version || version || fallbackVersion;
          buildDate = info.buildDate || '';
          arch = info.arch || '';
          os = info.os || '';
          license = info.license || 'BUSL-1.1';
        }
      } catch {
        // getBuildInfo failed; try the simpler native version command before
        // falling back to the build-time JS constant, which can be stale on
        // mobile if the frontend bundle lagged the native version.
        try {
          const native = await getAppVersion();
          if (sequence !== loadSequence) return;
          if (native) version = native;
        } catch {
          version = version || fallbackVersion;
        }
      }

      try {
        const update = await checkForUpdates({ force: true });
        if (sequence !== loadSequence) return;
        if (update?.available) {
          updateStatus = `Update available: v${update.version}`;
          availableUpdate = update;
        } else {
          updateStatus = version ? `Up to date (v${version})` : 'Up to date';
          availableUpdate = null;
        }
      } catch {
        if (sequence !== loadSequence) return;
        updateStatus = 'Unable to check';
        availableUpdate = null;
      }
    } else {
      version = version || fallbackVersion;
      buildDate = '';
      arch = '';
      os = '';
      license = 'BUSL-1.1';
    }

    if (sequence === loadSequence) {
      loading = false;
      loaded = true;
    }
  };

  $effect(() => {
    if (!open) return;
    void loadAboutInfo();
  });

  const handleInstall = async () => {
    if (!availableUpdate || installing) return;
    installing = true;
    installError = '';
    installProgress = 0;
    try {
      await downloadAndInstall(
        availableUpdate,
        ({ downloaded, contentLength }: { downloaded: number; contentLength: number }) => {
          if (contentLength > 0) {
            installProgress = Math.min(1, downloaded / contentLength);
          }
        },
      );
    } catch (err: unknown) {
      installError = (
        err && typeof err === 'object' && 'message' in err && typeof err.message === 'string'
          ? err.message
          : 'Update failed'
      ) as string;
      installing = false;
    }
  };

  const close = () => {
    if (installing) return;
    open = false;
    onClose?.();
  };

  const handleKeydown = (e: KeyboardEvent) => {
    if (e.key === 'Escape') close();
  };
</script>

{#if open}
  <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
  <div
    class="fixed inset-0 z-[100] flex items-center justify-center bg-black/50"
    onclick={(e) => {
      if (e.target === e.currentTarget) close();
    }}
    onkeydown={handleKeydown}
    role="dialog"
    aria-modal="true"
    aria-label="About Forward Email"
  >
    <div class="w-[420px] overflow-hidden rounded-lg border border-border bg-background shadow-xl">
      <div class="flex items-start justify-between p-5 pb-0">
        <div class="flex items-center gap-3">
          <img src="/icons/icon-256.png" alt="Forward Email" class="h-14 w-14 rounded-xl" />
          <div>
            <h2 class="text-lg font-semibold">Forward Email</h2>
            <p class="text-sm text-muted-foreground">Privacy-focused email</p>
          </div>
        </div>
        <button class="rounded-md p-1 hover:bg-accent" onclick={close} aria-label="Close">
          <X class="h-4 w-4" />
        </button>
      </div>

      {#if loaded && !loading}
        <div class="space-y-3 p-5">
          <dl class="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 text-sm">
            <dt class="text-muted-foreground">Version</dt>
            <dd class="font-mono">{version}</dd>

            {#if buildDate}
              <dt class="text-muted-foreground">Built</dt>
              <dd>{buildDate}</dd>
            {/if}

            {#if os || arch}
              <dt class="text-muted-foreground">Platform</dt>
              <dd>{osLabels[os] || os} ({archLabel(os, arch)})</dd>
            {/if}

            <dt class="text-muted-foreground">Update</dt>
            <dd>{updateStatus}</dd>

            <dt class="text-muted-foreground">License</dt>
            <dd>{license || 'BUSL-1.1'}</dd>
          </dl>

          {#if isTauriDesktop && availableUpdate?.available}
            <div class="rounded-md border border-sky-500/40 bg-sky-500/10 p-3 text-sm">
              <div class="mb-2 font-medium">
                Update available: v{availableUpdate.version}
              </div>
              {#if availableUpdate.body}
                <div
                  class="mb-3 max-h-32 overflow-y-auto whitespace-pre-wrap text-xs text-muted-foreground"
                >
                  {availableUpdate.body}
                </div>
              {/if}
              {#if installing}
                <div class="space-y-2">
                  <div class="h-1.5 w-full overflow-hidden rounded bg-muted">
                    <div
                      class="h-full bg-sky-500 transition-all"
                      style="width: {Math.round(installProgress * 100)}%"
                    ></div>
                  </div>
                  <div class="text-xs text-muted-foreground">
                    Downloading… {Math.round(installProgress * 100)}%
                  </div>
                </div>
              {:else}
                <div class="flex items-center gap-2">
                  <Button size="sm" onclick={handleInstall}>
                    <Download class="mr-1.5 h-3.5 w-3.5" />
                    Install and restart
                  </Button>
                  <Button
                    size="sm"
                    variant="ghost"
                    onclick={() =>
                      openExternal(
                        'https://github.com/forwardemail/mail.forwardemail.net/releases',
                      )}
                  >
                    View on GitHub
                  </Button>
                </div>
              {/if}
              {#if installError}
                <div class="mt-2 text-xs text-destructive">{installError}</div>
              {/if}
            </div>
          {/if}

          <div class="border-t border-border pt-3 text-xs text-muted-foreground">
            <p>
              Made by the <button
                class="text-sky-500 hover:underline inline cursor-pointer"
                onclick={() => openExternal('https://forwardemail.net/about')}>Forward Email</button
              > team. Open-source, privacy-first, no tracking.
            </p>
            <p class="mt-2">
              <button
                class="text-sky-500 hover:underline inline cursor-pointer"
                onclick={() => openExternal('https://forwardemail.net/privacy')}
                >Privacy Policy</button
              >
            </p>
            <p class="mt-2">
              <button
                class="hover:underline inline cursor-pointer"
                onclick={() => {
                  close();
                  globalThis.history.pushState({}, '', '/mailbox/diagnostics');
                  globalThis.dispatchEvent(new PopStateEvent('popstate'));
                }}>Run diagnostics</button
              >
            </p>
          </div>

          <div class="flex items-center gap-2 pt-1">
            <Button
              variant="outline"
              size="sm"
              onclick={() =>
                openExternal('https://github.com/forwardemail/mail.forwardemail.net/releases')}
            >
              <ExternalLink class="mr-1.5 h-3.5 w-3.5" />
              Release Notes
            </Button>
            <Button
              variant="outline"
              size="sm"
              onclick={() => openExternal('https://forwardemail.net')}
            >
              <ExternalLink class="mr-1.5 h-3.5 w-3.5" />
              Website
            </Button>
          </div>
        </div>
      {:else}
        <div class="flex items-center justify-center p-10 text-sm text-muted-foreground">
          Loading...
        </div>
      {/if}
    </div>
  </div>
{/if}
