<script lang="ts">
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
  import { spotifyAuth, loadSpotifyAuth, saveClientCredentials, saveTokens, saveUser, clearSpotifyAuth, saveCacheTimestamp } from '$lib/stores/spotify';
  import { spotifyAPI } from '$lib/services/spotify';
  import { start, onUrl } from '@fabianlars/tauri-plugin-oauth';
  import { openUrl } from '@tauri-apps/plugin-opener';
  import {
    getCachedPlaylists,
    getCachedAlbums,
    getCachedArtists,
    getCachedTracks,
    upsertPlaylists,
    upsertAlbums,
    upsertArtists,
    upsertTracks,
    type SpotifyPlaylist,
    type SpotifyAlbum,
    type SpotifyArtist,
    type SpotifyTrack
  } from '$lib/library/spotify-database';

  // Fixed port for OAuth callback - user must register this in Spotify Dashboard
  const OAUTH_PORT = 8228;
  const REDIRECT_URI = `http://127.0.0.1:${OAUTH_PORT}/callback`;

  // Login form state
  let clientIdInput = $state('');
  let clientSecretInput = $state('');
  let isAuthenticating = $state(false);
  let loginError = $state('');
  let loginSuccess = $state('');

  // OAuth state
  let isWaitingForCallback = $state(false);
  let oauthUnlisten: (() => void) | null = $state(null);

  // Data state
  type ViewMode = 'playlists' | 'tracks' | 'artists' | 'albums' | 'info';
  let viewMode = $state<ViewMode>('playlists');
  let playlists = $state<SpotifyPlaylist[]>([]);
  let albums = $state<SpotifyAlbum[]>([]);
  let artists = $state<SpotifyArtist[]>([]);
  let tracks = $state<SpotifyTrack[]>([]);
  let loading = $state(true);
  let syncing = $state(false);
  let error = $state<string | null>(null);
  let selectedIndex = $state<number | null>(null);

  // User refresh state
  let refreshingUser = $state(false);
  let userRefreshMessage = $state('');

  const CACHE_DURATION = 24 * 60 * 60; // 24 hours in seconds

  onMount(async () => {
    await loadSpotifyAuth();

    // Check if we have client credentials stored
    if ($spotifyAuth.clientId) {
      clientIdInput = $spotifyAuth.clientId;
    }
    if ($spotifyAuth.clientSecret) {
      clientSecretInput = $spotifyAuth.clientSecret;
    }

    if ($spotifyAuth.loggedIn) {
      await loadFavorites();
    } else {
      loading = false;
    }
  });

  async function loadFavorites() {
    loading = true;
    error = null;

    try {
      spotifyAPI.setClientCredentials($spotifyAuth.clientId!, $spotifyAuth.clientSecret!);
      spotifyAPI.setTokens(
        $spotifyAuth.accessToken!,
        $spotifyAuth.refreshToken!,
        $spotifyAuth.expiresAt!
      );

      // Check if we need to refresh cache
      const now = Math.floor(Date.now() / 1000);
      const cacheAge = $spotifyAuth.cacheTimestamp ? now - $spotifyAuth.cacheTimestamp : Infinity;
      const needsRefresh = cacheAge > CACHE_DURATION;

      if (needsRefresh) {
        await refreshFavorites();
      } else {
        // Load from cache
        const [cachedPlaylists, cachedAlbums, cachedArtists, cachedTracks] = await Promise.all([
          getCachedPlaylists(),
          getCachedAlbums(),
          getCachedArtists(),
          getCachedTracks()
        ]);

        playlists = cachedPlaylists;
        albums = cachedAlbums;
        artists = cachedArtists;
        tracks = cachedTracks;
      }
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : String(e);
      if (errorMessage === 'REFRESH_TOKEN_REVOKED') {
        await clearSpotifyAuth();
        error = 'Your Spotify session has expired. Please log in again.';
      } else {
        error = 'Error loading favorites: ' + errorMessage;
      }
      viewMode = 'info';
    } finally {
      loading = false;
    }
  }

  async function refreshFavorites() {
    if (!$spotifyAuth.accessToken || syncing) {
      return;
    }

    syncing = true;
    error = null;

    try {
      spotifyAPI.setClientCredentials($spotifyAuth.clientId!, $spotifyAuth.clientSecret!);
      spotifyAPI.setTokens(
        $spotifyAuth.accessToken,
        $spotifyAuth.refreshToken!,
        $spotifyAuth.expiresAt!
      );

      // Fetch all favorites from API
      console.log('[Spotify] Fetching favorites from API...');
      const [apiPlaylists, apiAlbums, apiArtists, apiTracks] = await Promise.all([
        spotifyAPI.getAllUserPlaylists(),
        spotifyAPI.getAllUserAlbums(),
        spotifyAPI.getAllUserArtists(),
        spotifyAPI.getAllUserTracks()
      ]);

      console.log('[Spotify] Fetched from API:', {
        playlists: apiPlaylists.length,
        albums: apiAlbums.length,
        artists: apiArtists.length,
        tracks: apiTracks.length
      });

      // Update database cache
      console.log('[Spotify] Updating database cache...');
      await upsertPlaylists(apiPlaylists);
      await upsertAlbums(apiAlbums);
      await upsertArtists(apiArtists);
      await upsertTracks(apiTracks);

      // Update cache timestamp
      const now = Math.floor(Date.now() / 1000);
      await saveCacheTimestamp(now);

      console.log('[Spotify] Reloading from cache...');
      // Reload from cache
      const [cachedPlaylists, cachedAlbums, cachedArtists, cachedTracks] = await Promise.all([
        getCachedPlaylists(),
        getCachedAlbums(),
        getCachedArtists(),
        getCachedTracks()
      ]);

      playlists = cachedPlaylists;
      albums = cachedAlbums;
      artists = cachedArtists;
      tracks = cachedTracks;

      console.log('[Spotify] Refresh complete!');
    } catch (e) {
      console.error('Error refreshing favorites:', e);
      const errorMessage = e instanceof Error ? e.message : String(e);
      if (errorMessage === 'REFRESH_TOKEN_REVOKED') {
        await clearSpotifyAuth();
        error = 'Your Spotify session has expired. Please log in again.';
      } else {
        error = 'Error refreshing favorites: ' + errorMessage;
      }
      viewMode = 'info';
    } finally {
      syncing = false;
    }
  }

  async function handleAuthorize() {
    if (!clientIdInput || !clientSecretInput) {
      loginError = 'Please enter both Client ID and Client Secret';
      return;
    }

    if (clientIdInput.trim().length === 0 || clientSecretInput.trim().length === 0) {
      loginError = 'Client ID and Client Secret cannot be empty';
      return;
    }

    isAuthenticating = true;
    loginError = '';
    loginSuccess = '';

    try {
      // Save credentials
      await saveClientCredentials(clientIdInput.trim(), clientSecretInput.trim());

      // Clean up any existing OAuth listener
      if (oauthUnlisten) {
        oauthUnlisten();
      }

      // Set up OAuth callback listener and store unlisten function
      oauthUnlisten = await onUrl((callbackUrl) => {
        handleOAuthCallback(callbackUrl);
      });

      // Start OAuth server on fixed port with custom styled response
      const port = await start({
        ports: [OAUTH_PORT],
        response: `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Spotify Authorization Complete</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: "Pixelated MS Sans Serif", Arial, sans-serif;
      background: #008080;
      display: flex;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      padding: 20px;
    }
    .window {
      background: silver;
      box-shadow: inset -1px -1px #0a0a0a, inset 1px 1px #fff, inset -2px -2px grey, inset 2px 2px #dfdfdf;
      padding: 3px;
      max-width: 500px;
      width: 100%;
    }
    .title-bar {
      background: linear-gradient(90deg, navy, #1084d0);
      padding: 3px 5px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      color: white;
      font-weight: bold;
      font-size: 11px;
    }
    .window-body {
      background: silver;
      padding: 16px;
      margin: 3px;
    }
    h1 {
      font-size: 16px;
      margin-bottom: 12px;
    }
    p {
      font-size: 11px;
      line-height: 1.5;
      margin-bottom: 8px;
    }
  </style>
</head>
<body>
  <div class="window">
    <div class="title-bar">
      <span>Spotify Authorization</span>
    </div>
    <div class="window-body">
      <h1>Authorization Complete</h1>
      <p>You have successfully authorized Shark with your Spotify account.</p>
      <p>You can close this window and return to the app.</p>
    </div>
  </div>
</body>
</html>
        `
      });
      console.log(`[Spotify] OAuth server started on port ${port}`);

      // Generate authorization URL
      const { url, codeVerifier } = await spotifyAPI.getAuthorizationUrl(
        clientIdInput.trim(),
        REDIRECT_URI
      );

      // Store code verifier for callback
      localStorage.setItem('spotify_code_verifier', codeVerifier);

      isWaitingForCallback = true;

      // Open Spotify authorization in default browser
      await openUrl(url);
    } catch (error) {
      console.error('[Spotify] Authorization error:', error);
      loginError = `Authorization error: ${error instanceof Error ? error.message : JSON.stringify(error)}`;
      isAuthenticating = false;
      isWaitingForCallback = false;
    }
  }

  async function handleOAuthCallback(callbackUrl: string) {
    // Immediately remove the listener to prevent duplicate calls from hot reload
    if (oauthUnlisten) {
      oauthUnlisten();
      oauthUnlisten = null;
    }

    try {
      // Parse the callback URL
      const url = new URL(callbackUrl);
      const code = url.searchParams.get('code');
      const error = url.searchParams.get('error');

      if (error) {
        throw new Error(`Authorization failed: ${error}`);
      }

      if (!code) {
        throw new Error('No authorization code received');
      }

      // Retrieve code verifier from localStorage
      const codeVerifier = localStorage.getItem('spotify_code_verifier');

      if (!codeVerifier) {
        throw new Error('OAuth state lost. Please try logging in again.');
      }

      // Exchange code for tokens
      const tokenData = await spotifyAPI.exchangeCodeForToken(
        code,
        codeVerifier,
        $spotifyAuth.clientId!,
        REDIRECT_URI
      );

      // Save tokens
      await saveTokens(tokenData.access_token, tokenData.refresh_token, tokenData.expires_in);

      // Set tokens in API client
      spotifyAPI.setClientCredentials($spotifyAuth.clientId!, $spotifyAuth.clientSecret!);
      spotifyAPI.setTokens(
        tokenData.access_token,
        tokenData.refresh_token,
        Date.now() + (tokenData.expires_in * 1000)
      );

      // Fetch user info
      const user = await spotifyAPI.getCurrentUser();
      await saveUser(user);

      // Load favorites after successful login
      await loadFavorites();

      // Clean up
      localStorage.removeItem('spotify_code_verifier');
    } catch (error) {
      loginError = `Authentication error: ${error instanceof Error ? error.message : 'Unknown error'}`;
      localStorage.removeItem('spotify_code_verifier');
    } finally {
      isAuthenticating = false;
      isWaitingForCallback = false;
    }
  }

  async function handleLogout() {
    await clearSpotifyAuth();
    clientIdInput = '';
    clientSecretInput = '';
    loginSuccess = '';
    loginError = '';
    playlists = [];
    albums = [];
    artists = [];
    tracks = [];
  }

  async function handleRefreshUser() {
    if (!$spotifyAuth.accessToken || !$spotifyAuth.clientId || !$spotifyAuth.clientSecret) {
      return;
    }

    refreshingUser = true;
    userRefreshMessage = '';

    try {
      // Set credentials in API client
      spotifyAPI.setClientCredentials($spotifyAuth.clientId, $spotifyAuth.clientSecret);
      spotifyAPI.setTokens(
        $spotifyAuth.accessToken,
        $spotifyAuth.refreshToken!,
        $spotifyAuth.expiresAt!
      );

      // Fetch updated user info
      const user = await spotifyAPI.getCurrentUser();
      await saveUser(user);

      userRefreshMessage = 'User info refreshed successfully!';
      setTimeout(() => {
        userRefreshMessage = '';
      }, 3000);
    } catch (error) {
      userRefreshMessage = 'Error refreshing user info: ' + (error instanceof Error ? error.message : 'Unknown error');
    } finally {
      refreshingUser = false;
      setTimeout(() => {
        userRefreshMessage = '';
      }, 3000);
    }
  }

  function handleItemClick(index: number) {
    selectedIndex = index;
  }

  function handlePlaylistDoubleClick(playlistId: string) {
    goto(`/services/spotify/playlists/${playlistId}`);
  }

  function formatDuration(ms: number): string {
    const mins = Math.floor(ms / 60000);
    const secs = Math.floor((ms % 60000) / 1000);
    return `${mins}:${String(secs).padStart(2, '0')}`;
  }
</script>

<div class="spotify-wrapper">
  <h2 style="padding: 8px">Spotify</h2>

  {#if !$spotifyAuth.loggedIn}
    <!-- Login Form -->
    <section class="window login-section" style="max-width: 600px; margin: 8px;">
      <div class="title-bar">
        <div class="title-bar-text">Login to Spotify</div>
      </div>
      <div class="window-body">
        <p>Enter your Spotify Developer credentials and authorize access:</p>

        <div class="field-row-stacked">
          <label for="client-id-input">Client ID</label>
          <input
            id="client-id-input"
            type="text"
            bind:value={clientIdInput}
            placeholder="Your Spotify App Client ID"
            disabled={isAuthenticating || isWaitingForCallback}
          />
        </div>

        <div class="field-row-stacked">
          <label for="client-secret-input">Client Secret</label>
          <input
            id="client-secret-input"
            type="password"
            bind:value={clientSecretInput}
            placeholder="Your Spotify App Client Secret"
            disabled={isAuthenticating || isWaitingForCallback}
          />
        </div>

        {#if loginError}
          <div class="error-message">
            ⚠ {loginError}
          </div>
        {/if}

        {#if isWaitingForCallback}
          <div class="info-message">
            Waiting for authorization in your browser... Please complete the login process.
          </div>
        {/if}

        <div class="button-row">
          <button onclick={handleAuthorize} disabled={isAuthenticating || isWaitingForCallback}>
            {isAuthenticating ? 'Authorizing...' : 'Authorize with Spotify'}
          </button>
        </div>

        <p style="margin-top: 8px; font-size: 11px; opacity: 0.7;">
          This will open Spotify's login page in your default browser.
        </p>

        <details class="instructions">
          <summary>How to get your Spotify Developer credentials</summary>
          <div class="instructions-content">
            <ol>
              <li>Go to <strong>developer.spotify.com/dashboard</strong></li>
              <li>Log in with your Spotify account</li>
              <li>Click <strong>"Create app"</strong></li>
              <li>Fill in the app details:
                <ul>
                  <li>App name: (any name you want, e.g., "Shark Music Player")</li>
                  <li>App description: (any description)</li>
                  <li>Redirect URI: <code>http://127.0.0.1:8228/callback</code></li>
                  <li>Check the Web API box</li>
                </ul>
              </li>
              <li>Click <strong>"Save"</strong></li>
              <li>Click <strong>"Settings"</strong> on your new app</li>
              <li>Copy the <strong>Client ID</strong> (visible by default)</li>
              <li>Click <strong>"View client secret"</strong> and copy the <strong>Client Secret</strong></li>
              <li>Paste both values into the fields above</li>
            </ol>
            <p><strong>Note:</strong> The Client ID and Client Secret are used to authenticate your app with Spotify. Keep the Client Secret private and never share it publicly.</p>
            <p><strong>Important:</strong> The Redirect URI must be exactly <code>http://127.0.0.1:8228/callback</code>. Port 8228 must be available when authorizing. If you get a port error, close any application using port 8228.</p>
            <p><strong>Scopes used:</strong> This app requests access to your profile, email, saved library (tracks, albums), playlists (including private and collaborative), and followed artists.</p>
          </div>
        </details>
      </div>
    </section>
  {:else if loading}
    <p style="padding: 8px;">Loading favorites...</p>
  {:else}
    <section class="favorites-content">
      <!-- Tabs -->
      <!--
        svelte-ignore a11y_no_noninteractive_element_to_interactive_role
        Reason: 98.css library requires <menu role="tablist"> for proper tab styling.
      -->
      <menu role="tablist">
        <li role="tab" aria-selected={viewMode === 'playlists'}>
          <button onclick={() => viewMode = 'playlists'}>Playlists</button>
        </li>
        <li role="tab" aria-selected={viewMode === 'tracks'}>
          <button onclick={() => viewMode = 'tracks'}>Tracks</button>
        </li>
        <li role="tab" aria-selected={viewMode === 'artists'}>
          <button onclick={() => viewMode = 'artists'}>Artists</button>
        </li>
        <li role="tab" aria-selected={viewMode === 'albums'}>
          <button onclick={() => viewMode = 'albums'}>Albums</button>
        </li>
        <li role="tab" aria-selected={viewMode === 'info'}>
          <button onclick={() => viewMode = 'info'}>Info</button>
        </li>
      </menu>

      <!-- Tab Content -->
      <div class="window tab-content" role="tabpanel">
        <div class="window-body">
          {#if syncing}
            <div class="sync-status">
              <p>Refreshing favorites from Spotify...</p>
            </div>
          {:else if viewMode === 'playlists'}
            <!-- Playlists View -->
            <div class="tab-header">
              <h4>Favorite Playlists</h4>
              <button onclick={refreshFavorites} disabled={syncing}>
                Refresh
              </button>
            </div>
            <div class="sunken-panel table-container">
              <table class="interactive">
                <thead>
                  <tr>
                    <th>Playlist</th>
                    <th>Tracks</th>
                  </tr>
                </thead>
                <tbody>
                  <!-- Virtual Spotify Likes Playlist (only show if we have favorite tracks) -->
                  {#if tracks.length > 0}
                    <tr
                      class:highlighted={selectedIndex === -1}
                      class="favorite-tracks-row"
                      onclick={() => handleItemClick(-1)}
                      ondblclick={() => handlePlaylistDoubleClick('spotify-likes')}
                    >
                      <td>Spotify Likes</td>
                      <td>{tracks.length}</td>
                    </tr>
                  {/if}

                  <!-- User Playlists -->
                  {#each playlists as playlist, i}
                    <tr
                      class:highlighted={selectedIndex === i}
                      onclick={() => handleItemClick(i)}
                      ondblclick={() => handlePlaylistDoubleClick(playlist.id)}
                    >
                      <td>{playlist.name}</td>
                      <td>{playlist.track_count}</td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            </div>
          {:else if viewMode === 'tracks'}
            <!-- Tracks View -->
            <div class="tab-header">
              <h4>Favorite Tracks</h4>
              <button onclick={refreshFavorites} disabled={syncing}>
                Refresh
              </button>
            </div>
            <div class="sunken-panel table-container">
              <table class="interactive">
                <thead>
                  <tr>
                    <th>Title</th>
                    <th>Artist</th>
                    <th>Album</th>
                    <th>Duration</th>
                  </tr>
                </thead>
                <tbody>
                  {#each tracks as track, i}
                    <tr
                      class:highlighted={selectedIndex === i}
                      onclick={() => handleItemClick(i)}
                    >
                      <td>{track.name}</td>
                      <td>{track.artist_name}</td>
                      <td>{track.album_name}</td>
                      <td class="duration">{formatDuration(track.duration_ms)}</td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            </div>
          {:else if viewMode === 'artists'}
            <!-- Artists View -->
            <div class="tab-header">
              <h4>Followed Artists</h4>
              <button onclick={refreshFavorites} disabled={syncing}>
                Refresh
              </button>
            </div>
            <div class="sunken-panel table-container">
              <table class="interactive">
                <thead>
                  <tr>
                    <th>Artist</th>
                    <th>Followers</th>
                  </tr>
                </thead>
                <tbody>
                  {#each artists as artist, i}
                    <tr
                      class:highlighted={selectedIndex === i}
                      onclick={() => handleItemClick(i)}
                    >
                      <td>{artist.name}</td>
                      <td>{artist.followers.toLocaleString()}</td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            </div>
          {:else if viewMode === 'albums'}
            <!-- Albums View -->
            <div class="tab-header">
              <h4>Saved Albums</h4>
              <button onclick={refreshFavorites} disabled={syncing}>
                Refresh
              </button>
            </div>
            <div class="sunken-panel table-container">
              <table class="interactive">
                <thead>
                  <tr>
                    <th>Album</th>
                    <th>Artist</th>
                    <th>Year</th>
                  </tr>
                </thead>
                <tbody>
                  {#each albums as album, i}
                    <tr
                      class:highlighted={selectedIndex === i}
                      onclick={() => handleItemClick(i)}
                    >
                      <td>{album.name}</td>
                      <td>{album.artist_name}</td>
                      <td>{album.release_date ? new Date(album.release_date).getFullYear() : '—'}</td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            </div>
          {:else if viewMode === 'info'}
            <!-- User Info View -->
            <div class="user-container">
              {#if error}
                <fieldset>
                  <legend>Error</legend>
                  <div class="error-message">
                    {error}
                  </div>
                </fieldset>
              {/if}

              <fieldset>
                <legend>User Information</legend>
                <div class="field-row">
                  <span class="field-label">Name:</span>
                  <span>{$spotifyAuth.user?.display_name || 'Unknown'}</span>
                </div>
                <div class="field-row">
                  <span class="field-label">Email:</span>
                  <span>{$spotifyAuth.user?.email || 'N/A'}</span>
                </div>
                <div class="field-row">
                  <span class="field-label">Country:</span>
                  <span>{$spotifyAuth.user?.country || 'N/A'}</span>
                </div>
                <div class="field-row">
                  <span class="field-label">Subscription:</span>
                  <span>{$spotifyAuth.user?.product ? $spotifyAuth.user.product.toUpperCase() : 'Unknown'}</span>
                </div>
              </fieldset>

              {#if userRefreshMessage}
                <div class="message-box">
                  {userRefreshMessage}
                </div>
              {/if}

              <fieldset style="margin-top: 16px;">
                <legend>Actions</legend>
                <div class="button-row">
                  <button onclick={handleRefreshUser} disabled={refreshingUser}>
                    {refreshingUser ? 'Refreshing...' : 'Refresh User Info'}
                  </button>
                  <button onclick={refreshFavorites} disabled={syncing}>
                    {syncing ? 'Refreshing...' : 'Refresh Cache'}
                  </button>
                  <button onclick={handleLogout}>Logout</button>
                </div>
              </fieldset>
            </div>
          {/if}
        </div>
      </div>
    </section>
  {/if}
</div>

<style>
  .spotify-wrapper {
    height: 100%;
    display: flex;
    flex-direction: column;
  }

  h2 {
    margin: 0;
  }

  .login-section {
    margin-bottom: 16px;
  }

  .favorites-content {
    margin: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .tab-content {
    margin-top: -2px;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .tab-content .window-body {
    padding: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .tab-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px;
    border-bottom: 1px solid var(--button-shadow, #808080);
  }

  .tab-header h4 {
    margin: 0;
  }

  .table-container {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
  }

  table {
    width: 100%;
  }

  th {
    text-align: left;
  }

  .duration {
    font-family: monospace;
    font-size: 0.9em;
    text-align: center;
    width: 80px;
  }

  .user-container {
    padding: 16px;
  }

  .message-box {
    padding: 8px;
    margin: 8px 0;
    background-color: var(--button-shadow, #2a2a2a);
    border: 1px solid var(--button-highlight, #606060);
  }

  .sync-status {
    padding: 16px 8px;
    text-align: center;
  }

  .favorite-tracks-row {
    font-weight: bold;
  }

  .window-body {
    padding: 12px;
  }

  .field-row-stacked {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 12px;
  }

  .field-row {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
  }

  .field-label {
    font-weight: bold;
    min-width: 120px;
  }

  input[type="text"],
  input[type="password"] {
    width: 100%;
    padding: 4px;
  }

  .button-row {
    margin-top: 12px;
    display: flex;
    gap: 8px;
  }

  .error-message {
    background-color: #ffcccc;
    color: #cc0000;
    padding: 8px;
    margin: 8px 0;
    border: 1px solid #cc0000;
  }

  .info-message {
    background-color: #cce5ff;
    color: #004085;
    padding: 8px;
    margin: 8px 0;
    border: 1px solid #004085;
  }

  .instructions {
    margin-top: 16px;
    padding: 8px;
    background-color: var(--button-shadow, #2a2a2a);
  }

  .instructions summary {
    cursor: pointer;
    font-weight: bold;
    user-select: none;
  }

  .instructions-content {
    margin-top: 8px;
    padding-left: 4px;
  }

  .instructions-content ol {
    margin: 8px 0;
    padding-left: 20px;
  }

  .instructions-content ul {
    margin: 4px 0;
    padding-left: 20px;
  }

  .instructions-content li {
    margin: 6px 0;
    line-height: 1.4;
  }

  .instructions-content strong {
    font-weight: bold;
  }

  .instructions-content code {
    background-color: var(--button-highlight, #505050);
    padding: 2px 4px;
    border-radius: 2px;
    font-family: monospace;
    font-size: 0.9em;
  }

  .instructions-content p {
    margin: 8px 0;
    line-height: 1.5;
  }
</style>
