<script lang="ts">
  import { prewarmCaches, type PrewarmProgress } from '../../services/cache/cache-prewarmer.js';
  import { markVersionUpdated, getAppVersion } from '../../services/version-manager.js';
  import { getDB } from '../../services/cache/indexeddb-store.js';
  import Icon from '../ui/Icon.svelte';
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';

  interface Props {
    onComplete: () => void;
  }

  let { onComplete }: Props = $props();

  let updating = $state(false);
  let updateComplete = $state(false);
  let showPWAUpdatePrompt = $state(false);
  let appVersion = $state('0.2.0');
  let isPWAInstalled = $state(false);
  let progress = $state<PrewarmProgress>({
    step: 'Preparing update...',
    progress: 0,
    total: 7,
    current: 0
  });

  onMount(async () => {
    appVersion = await getAppVersion();
    
    // Check if PWA is installed
    if (typeof window !== 'undefined') {
      const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
      const isIOSStandalone = (window.navigator as any).standalone === true;
      isPWAInstalled = isStandalone || isIOSStandalone;
    }
  });

  async function handleUpdate() {
    updating = true;
    progress = {
      step: 'Starting update...',
      progress: 0,
      total: 7,
      current: 0
    };

    try {
      // Step 1: Ensure database is up to date (with timeout)
      progress = {
        step: 'Updating database structure...',
        progress: 5,
        total: 8,
        current: 1
      };
      
      // Add timeout to prevent hanging
      await Promise.race([
        getDB(),
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('Database update timed out after 10 seconds')), 10000)
        )
      ]).catch(async (error) => {
        // If timeout, try to continue anyway (database might still work)
        console.warn('Database update timeout, continuing:', error);
        try {
          // Try to get DB one more time without timeout
          await getDB();
        } catch (e) {
          console.warn('Failed to get database after timeout:', e);
          // Continue anyway - the app might still work
        }
      });

      // Step 2: Clean up service workers and caches
      progress = {
        step: 'Cleaning up service workers...',
        progress: 10,
        total: 8,
        current: 2
      };
      await cleanupServiceWorkers();

      // Step 3: Prewarm caches
      await prewarmCaches((prog) => {
        progress = {
          ...prog,
          progress: 15 + Math.round((prog.progress * 75) / 100) // Map 0-100 to 15-90
        };
      });

      // Step 4: Mark version as updated
      progress = {
        step: 'Finalizing update...',
        progress: 95,
        total: 8,
        current: 8
      };
      await markVersionUpdated();

      // Step 5: Complete
      progress = {
        step: 'Update complete!',
        progress: 100,
        total: 8,
        current: 8
      };

      // Small delay to show completion
      await new Promise(resolve => setTimeout(resolve, 500));

      updateComplete = true;
      
      // If PWA is installed, ask if they want to update it
      if (isPWAInstalled) {
        showPWAUpdatePrompt = true;
      } else {
        // Not a PWA, route to about page and complete
        onComplete();
        goto('/about');
      }
    } catch (error) {
      progress = {
        step: `Update error: ${error instanceof Error ? error.message : 'Unknown error'}`,
        progress: 0,
        total: 7,
        current: 0
      };
      console.error('Update failed:', error);
    }
  }

  /**
   * Clean up service workers and caches to prevent corrupted content errors
   */
  async function cleanupServiceWorkers(): Promise<void> {
    if (typeof window === 'undefined' || !('serviceWorker' in navigator)) {
      return;
    }

    try {
      // Get all service worker registrations
      const registrations = await navigator.serviceWorker.getRegistrations();
      
      // Unregister all service workers
      await Promise.all(
        registrations.map(async (registration) => {
          try {
            // Clear all caches for this registration
            if (registration.active) {
              const cacheNames = await caches.keys();
              await Promise.all(
                cacheNames.map(cacheName => caches.delete(cacheName))
              );
            }
            
            // Unregister the service worker
            const unregistered = await registration.unregister();
            if (unregistered) {
              console.log('Service worker unregistered successfully');
            }
          } catch (error) {
            console.warn('Failed to unregister service worker:', error);
            // Continue with other registrations even if one fails
          }
        })
      );

      // Also try to clear all caches (in case some weren't associated with registrations)
      try {
        const cacheNames = await caches.keys();
        await Promise.all(
          cacheNames.map(cacheName => caches.delete(cacheName))
        );
        if (cacheNames.length > 0) {
          console.log(`Cleared ${cacheNames.length} cache(s)`);
        }
      } catch (error) {
        console.warn('Failed to clear some caches:', error);
        // Non-critical, continue
      }
    } catch (error) {
      console.warn('Service worker cleanup encountered errors (non-critical):', error);
      // Non-critical - continue with update even if cleanup fails
    }
  }

  async function handlePWAUpdate() {
    try {
      // Check for service worker update
      if ('serviceWorker' in navigator) {
        const registration = await navigator.serviceWorker.getRegistration();
        if (registration) {
          // Check for updates
          await registration.update();
          
          // If there's a waiting service worker, skip waiting and reload
          if (registration.waiting) {
            registration.waiting.postMessage({ type: 'SKIP_WAITING' });
          }
          
          // Store route to about page before reload
          sessionStorage.setItem('postUpdateRedirect', '/about');
          
          // Reload to apply update
          window.location.reload();
          return;
        }
      }
      
      // If no service worker or update mechanism, route to about and reload
      sessionStorage.setItem('postUpdateRedirect', '/about');
      window.location.reload();
    } catch (error) {
      console.error('PWA update failed:', error);
      // Still reload to ensure update is applied
      sessionStorage.setItem('postUpdateRedirect', '/about');
      window.location.reload();
    }
  }
</script>

<div
  class="update-modal-overlay"
  role="dialog"
  aria-modal="true"
  aria-labelledby="update-modal-title"
  onclick={(e) => e.target === e.currentTarget && !updating && onComplete()}
  onkeydown={(e) => {
    if (e.key === 'Escape' && !updating) {
      onComplete();
    }
  }}
  tabindex="-1"
>
  <div class="update-modal">
    <div class="update-modal-header">
      <h2 id="update-modal-title" class="update-modal-title">New Version Available</h2>
      <p class="update-modal-subtitle">
        Version {appVersion} is now available. Update to get the latest features and improvements.
      </p>
    </div>

    {#if !updating}
      <div class="update-modal-content">
        <p class="update-modal-description">
          This update will:
        </p>
        <ul class="update-modal-list">
          <li>Update the database structure</li>
          <li>Preload common data for faster performance</li>
          <li>Prepare caches for quick access</li>
        </ul>
      </div>

      <div class="update-modal-actions">
        <button
          onclick={handleUpdate}
          class="update-button"
          aria-label="Update to new version"
        >
          <Icon name="download" size={16} />
          <span>Update Now</span>
        </button>
        <button
          onclick={() => {
            onComplete();
            goto('/about');
          }}
          class="update-button-secondary"
          aria-label="Update later"
        >
          Update Later
        </button>
      </div>
    {:else if !updateComplete}
      <div class="update-modal-content">
        <div class="update-progress">
          <div class="update-progress-bar-container">
            <div
              class="update-progress-bar"
              style="width: {progress.progress}%"
            ></div>
          </div>
          <p class="update-progress-text">
            {progress.step} ({progress.progress}%)
          </p>
          <p class="update-progress-step">
            Step {progress.current} of {progress.total}
          </p>
        </div>
      </div>
    {:else if showPWAUpdatePrompt}
      <div class="update-modal-content">
        <p class="update-modal-description">
          The app update is complete! Since you have aitherboard installed as a PWA, would you like to update it now?
        </p>
        <p class="update-modal-note">
          This will reload the app to apply the PWA update.
        </p>
      </div>
      <div class="update-modal-actions">
        <button
          onclick={handlePWAUpdate}
          class="update-button"
          aria-label="Update PWA now"
        >
          <Icon name="download" size={16} />
          <span>Update PWA Now</span>
        </button>
        <button
          onclick={() => {
            onComplete();
            goto('/about');
          }}
          class="update-button-secondary"
          aria-label="Update PWA later"
        >
          Update Later
        </button>
      </div>
    {/if}
  </div>
</div>

<style>
  .update-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    padding: 1rem;
  }

  .update-modal {
    background: var(--fog-post, #ffffff);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.5rem;
    max-width: 500px;
    width: 100%;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  }

  :global(.dark) .update-modal {
    background: var(--fog-dark-post, #334155);
    border-color: var(--fog-dark-border, #475569);
  }

  .update-modal-header {
    padding: 1.5rem;
    border-bottom: 1px solid var(--fog-border, #e5e7eb);
  }

  :global(.dark) .update-modal-header {
    border-bottom-color: var(--fog-dark-border, #475569);
  }

  .update-modal-title {
    margin: 0 0 0.5rem 0;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--fog-text, #1f2937);
  }

  :global(.dark) .update-modal-title {
    color: var(--fog-dark-text, #f9fafb);
  }

  .update-modal-subtitle {
    margin: 0;
    font-size: 0.875rem;
    color: var(--fog-text-light, #52667a);
  }

  :global(.dark) .update-modal-subtitle {
    color: var(--fog-dark-text-light, #a8b8d0);
  }

  .update-modal-content {
    padding: 1.5rem;
  }

  .update-modal-description {
    margin: 0 0 1rem 0;
    color: var(--fog-text, #1f2937);
  }

  :global(.dark) .update-modal-description {
    color: var(--fog-dark-text, #f9fafb);
  }

  .update-modal-list {
    margin: 0;
    padding-left: 1.5rem;
    color: var(--fog-text, #1f2937);
  }

  :global(.dark) .update-modal-list {
    color: var(--fog-dark-text, #f9fafb);
  }

  .update-modal-list li {
    margin-bottom: 0.5rem;
  }

  .update-modal-note {
    margin: 1rem 0 0 0;
    font-size: 0.875rem;
    color: var(--fog-text-light, #52667a);
    font-style: italic;
  }

  :global(.dark) .update-modal-note {
    color: var(--fog-dark-text-light, #a8b8d0);
  }

  .update-modal-actions {
    padding: 1.5rem;
    border-top: 1px solid var(--fog-border, #e5e7eb);
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
  }

  :global(.dark) .update-modal-actions {
    border-top-color: var(--fog-dark-border, #475569);
  }

  .update-button {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    background: var(--fog-accent, #64748b);
    color: white;
    border: none;
    border-radius: 0.375rem;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    transition: opacity 0.2s;
  }

  .update-button:hover {
    opacity: 0.9;
  }

  :global(.dark) .update-button {
    background: var(--fog-dark-accent, #94a3b8);
  }

  .update-button-secondary {
    padding: 0.75rem 1.5rem;
    background: var(--fog-highlight, #f3f4f6);
    color: var(--fog-text, #1f2937);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.375rem;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    transition: all 0.2s;
  }

  .update-button-secondary:hover {
    background: var(--fog-accent, #64748b);
    color: white;
    border-color: var(--fog-accent, #64748b);
  }

  :global(.dark) .update-button-secondary {
    background: var(--fog-dark-highlight, #475569);
    color: var(--fog-dark-text, #f9fafb);
    border-color: var(--fog-dark-border, #475569);
  }

  :global(.dark) .update-button-secondary:hover {
    background: var(--fog-dark-accent, #94a3b8);
    color: white;
    border-color: var(--fog-dark-accent, #94a3b8);
  }

  .update-progress {
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }

  .update-progress-bar-container {
    width: 100%;
    height: 8px;
    background: var(--fog-highlight, #f3f4f6);
    border-radius: 4px;
    overflow: hidden;
  }

  :global(.dark) .update-progress-bar-container {
    background: var(--fog-dark-highlight, #475569);
  }

  .update-progress-bar {
    height: 100%;
    background: var(--fog-accent, #64748b);
    border-radius: 4px;
    transition: width 0.3s ease;
  }

  :global(.dark) .update-progress-bar {
    background: var(--fog-dark-accent, #94a3b8);
  }

  .update-progress-text {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--fog-text, #1f2937);
    text-align: center;
  }

  :global(.dark) .update-progress-text {
    color: var(--fog-dark-text, #f9fafb);
  }

  .update-progress-step {
    margin: 0;
    font-size: 0.75rem;
    color: var(--fog-text-light, #52667a);
    text-align: center;
  }

  :global(.dark) .update-progress-step {
    color: var(--fog-dark-text-light, #a8b8d0);
  }
</style>
