<script lang="ts">
  import Header from '../../lib/components/layout/Header.svelte';
  import { sessionManager } from '../../lib/services/auth/session-manager.js';
  import { nostrClient } from '../../lib/services/nostr/nostr-client.js';
  import { relayManager } from '../../lib/services/nostr/relay-manager.js';
  import { config } from '../../lib/services/nostr/config.js';
  import { cacheRSSFeed, getCachedRSSFeed, type RSSItem } from '../../lib/services/cache/rss-cache.js';
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
  import type { NostrEvent } from '../../lib/types/nostr.js';
  import { KIND } from '../../lib/types/kind-lookup.js';
  import MarkdownRenderer from '../../lib/components/content/MarkdownRenderer.svelte';
  import RSSCommentForm from '../../lib/modules/rss/RSSCommentForm.svelte';
  import IconButton from '../../lib/components/ui/IconButton.svelte';

  const RSS_FEED_KIND = 10895;


  let currentPubkey = $state<string | null>(null);
  let rssEvent = $state<NostrEvent | null>(null);
  let loading = $state(true);
  let loadingFeeds = $state(false);
  let rssItems = $state<RSSItem[]>([]);
  let feedErrors = $state<Map<string, string>>(new Map());
  let feedsLoaded = $state(false); // Track if feeds have been loaded to prevent re-triggering
  let currentPage = $state(1);
  const itemsPerPage = 50;
  
  let subscribedFeeds = $derived.by(() => {
    if (!rssEvent) return [];
    return rssEvent.tags
      .filter(tag => tag[0] === 'u' && tag[1])
      .map(tag => tag[1]);
  });

  // Track the last feeds we loaded to detect changes
  let lastLoadedFeeds = $state<string[]>([]);

  // Computed: get items for current page
  let paginatedItems = $derived.by(() => {
    const start = (currentPage - 1) * itemsPerPage;
    const end = start + itemsPerPage;
    return rssItems.slice(start, end);
  });

  // Computed: total pages
  let totalPages = $derived.by(() => Math.ceil(rssItems.length / itemsPerPage));

  onMount(async () => {
    await nostrClient.initialize();
    const session = sessionManager.getSession();
    if (!session) {
      goto('/login');
      return;
    }

    currentPubkey = session.pubkey;
    await checkRssEvent();
  });

  $effect(() => {
    // Only load if:
    // 1. We have feeds to load
    // 2. We have an rssEvent
    // 3. We're not currently loading
    // 4. The feeds have changed (different URLs) or haven't been loaded yet
    const feedsChanged = JSON.stringify(subscribedFeeds) !== JSON.stringify(lastLoadedFeeds);
    if (subscribedFeeds.length > 0 && rssEvent && !loadingFeeds && (feedsChanged || !feedsLoaded)) {
      lastLoadedFeeds = [...subscribedFeeds];
      loadRssFeeds();
    } else if (subscribedFeeds.length === 0 && feedsLoaded) {
      // Reset if feeds were removed
      feedsLoaded = false;
      rssItems = [];
      feedErrors.clear();
      lastLoadedFeeds = [];
      currentPage = 1;
    }
  });

  // Reset to page 1 when items change significantly
  $effect(() => {
    if (rssItems.length > 0 && currentPage > totalPages) {
      currentPage = 1;
    }
  });

  async function checkRssEvent() {
    if (!currentPubkey) return;

    // Load from cache first (fast - instant display)
    try {
      const { getRecentCachedEvents } = await import('../../lib/services/cache/event-cache.js');
      const cachedEvents = await getRecentCachedEvents([RSS_FEED_KIND], 60 * 60 * 1000, 1); // 1 hour cache
      const cachedRssEvent = cachedEvents.find(e => e.pubkey === currentPubkey);
      
      if (cachedRssEvent) {
        // Only update if it's actually different (prevents unnecessary re-renders)
        if (!rssEvent || rssEvent.id !== cachedRssEvent.id) {
          rssEvent = cachedRssEvent;
          // Reset feeds loaded state when event changes
          feedsLoaded = false;
          lastLoadedFeeds = [];
        }
        loading = false; // Show cached content immediately
      } else {
        loading = true; // Only show loading if no cache
      }
    } catch (error) {
      // Cache error (non-critical)
      loading = true; // Show loading if cache check fails
    }

    try {
      const relays = relayManager.getProfileReadRelays();
      const events = await nostrClient.fetchEvents(
        [{ kinds: [RSS_FEED_KIND], authors: [currentPubkey], limit: 1 }],
        relays,
        { 
          useCache: 'cache-first', // Already shown cache above, now stream updates
          cacheResults: true,
          timeout: config.standardTimeout
        }
      );

      if (events.length > 0) {
        const newRssEvent = events[0];
        // Only update if it's actually different (prevents unnecessary re-renders)
        if (!rssEvent || rssEvent.id !== newRssEvent.id) {
          rssEvent = newRssEvent;
          // Reset feeds loaded state when event changes
          feedsLoaded = false;
          lastLoadedFeeds = [];
          currentPage = 1; // Reset to first page when event changes
        }
      }
    } catch (error) {
      // Failed to load RSS event
    } finally {
      loading = false;
    }
  }

  async function loadRssFeeds() {
    if (subscribedFeeds.length === 0 || loadingFeeds || feedsLoaded) return;
    
    loadingFeeds = true;
    feedErrors.clear();
    const allItems: RSSItem[] = [];
    
    try {
      // First, try to load from cache
      const cachePromises = subscribedFeeds.map(async (feedUrl) => {
        const cached = await getCachedRSSFeed(feedUrl);
        if (cached && cached.length > 0) {
          return { feedUrl, items: cached, fromCache: true };
        }
        return { feedUrl, items: null, fromCache: false };
      });
      
      const cacheResults = await Promise.all(cachePromises);
      
      // Add cached items immediately
      for (const result of cacheResults) {
        if (result.items) {
          allItems.push(...result.items);
        }
      }
      
      // If we have cached items, show them immediately
      if (allItems.length > 0) {
        allItems.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime());
        rssItems = allItems;
        feedsLoaded = true;
      }
      
      // Then fetch fresh data in background for feeds that need updating
      const feedsToFetch = cacheResults
        .filter(result => !result.fromCache || !result.items)
        .map(result => result.feedUrl);
      
      if (feedsToFetch.length > 0) {
        const fetchPromises = feedsToFetch.map(async (feedUrl) => {
          try {
            // Add timeout to prevent hanging requests
            const timeoutPromise = new Promise<never>((_, reject) => {
              setTimeout(() => reject(new Error('Request timeout')), 10000); // 10 second timeout
            });
            
            const items = await Promise.race([
              fetchRssFeed(feedUrl),
              timeoutPromise
            ]);
            
            // Cache the fetched items
            await cacheRSSFeed(feedUrl, items);
            return { feedUrl, items };
          } catch (error) {
            // Only log non-CORS errors to avoid console spam
            const errorMessage = error instanceof Error ? error.message : 'Failed to fetch feed';
            // Feed fetch failed (errors logged only for non-CORS/timeout issues)
            feedErrors.set(feedUrl, errorMessage);
            return { feedUrl, items: [] };
          }
        });
        
        const fetchResults = await Promise.all(fetchPromises);
        
        // Merge fresh items with cached items
        const freshItems: RSSItem[] = [];
        for (const result of fetchResults) {
          freshItems.push(...result.items);
        }
        
        // Combine with existing items and deduplicate by link
        const itemMap = new Map<string, RSSItem>();
        for (const item of allItems) {
          itemMap.set(item.link, item);
        }
        for (const item of freshItems) {
          itemMap.set(item.link, item);
        }
      
        // Sort by date (newest first)
        const combinedItems = Array.from(itemMap.values());
        combinedItems.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime());
      
        rssItems = combinedItems;
        currentPage = 1; // Reset to first page when items update
      }
      
      feedsLoaded = true;
    } catch (error) {
      // Failed to load RSS feeds
    } finally {
      loadingFeeds = false;
    }
  }

  async function fetchRssFeed(feedUrl: string): Promise<RSSItem[]> {
    // Always use a CORS proxy to avoid CORS errors
    // Direct fetch will fail for most RSS feeds due to CORS restrictions
      const proxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(feedUrl)}`;
    const response = await fetch(proxyUrl);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    const xmlText = await response.text();
    const parser = new DOMParser();
    const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
    
    // Check for parsing errors
    const parserError = xmlDoc.querySelector('parsererror');
    if (parserError) {
      throw new Error('Failed to parse RSS XML');
    }
    
    // Get feed title
    const feedTitle = xmlDoc.querySelector('channel > title')?.textContent?.trim() || 
                     xmlDoc.querySelector('title')?.textContent?.trim();
    
    // Parse items (handle both RSS 2.0 and Atom formats)
    const items: RSSItem[] = [];
    
    // RSS 2.0 format
    const rssItems = xmlDoc.querySelectorAll('item');
    rssItems.forEach((item) => {
      const title = item.querySelector('title')?.textContent?.trim() || 'Untitled';
      const link = item.querySelector('link')?.textContent?.trim() || '';
      const description = item.querySelector('description')?.textContent?.trim() || '';
      const pubDateStr = item.querySelector('pubDate')?.textContent?.trim() || '';
      
      let pubDate = new Date();
      if (pubDateStr) {
        const parsed = new Date(pubDateStr);
        if (!isNaN(parsed.getTime())) {
          pubDate = parsed;
        }
      }
      
      items.push({
        title,
        link,
        description,
        pubDate,
        feedUrl,
        feedTitle
      });
    });
    
    // Atom format (if no RSS items found)
    if (items.length === 0) {
      const atomEntries = xmlDoc.querySelectorAll('entry');
      atomEntries.forEach((entry) => {
        const title = entry.querySelector('title')?.textContent?.trim() || 'Untitled';
        const linkEl = entry.querySelector('link');
        const link = linkEl?.getAttribute('href') || linkEl?.textContent?.trim() || '';
        const description = entry.querySelector('summary')?.textContent?.trim() || 
                          entry.querySelector('content')?.textContent?.trim() || '';
        const pubDateStr = entry.querySelector('published')?.textContent?.trim() || 
                          entry.querySelector('updated')?.textContent?.trim() || '';
        
        let pubDate = new Date();
        if (pubDateStr) {
          const parsed = new Date(pubDateStr);
          if (!isNaN(parsed.getTime())) {
            pubDate = parsed;
          }
        }
        
        items.push({
          title,
          link,
          description,
          pubDate,
          feedUrl,
          feedTitle
        });
      });
    }
    
    return items;
  }

  function getRelativeTime(date: Date): string {
    const now = new Date();
    const diff = now.getTime() - date.getTime();
    const hours = Math.floor(diff / (1000 * 60 * 60));
    const days = Math.floor(diff / (1000 * 60 * 60 * 24));
    const minutes = Math.floor(diff / (1000 * 60));

    if (days > 0) return `${days}d ago`;
    if (hours > 0) return `${hours}h ago`;
    if (minutes > 0) return `${minutes}m ago`;
    return 'just now';
  }

  function handleCreateRss() {
    goto(`/write?kind=${RSS_FEED_KIND}`);
  }

  // Track which RSS item has reply form open
  let openReplyFormFor = $state<string | null>(null); // URL of the item

  function toggleReplyForm(itemLink: string) {
    if (openReplyFormFor === itemLink) {
      openReplyFormFor = null;
    } else {
      openReplyFormFor = itemLink;
    }
  }

  // Generate a deterministic thread ID from the URL (for RSS items, we use the URL as threadId)
  function getThreadIdFromUrl(url: string): string {
    // Use the URL as the threadId for RSS items
    return url;
  }
</script>

<Header />

<main class="container mx-auto px-4 py-8">
  <div class="rss-page">
    <h1 class="font-bold text-fog-text dark:text-fog-dark-text font-mono mb-6" style="font-size: 1.5em;">/RSS</h1>

    {#if loading}
      <p class="text-fog-text dark:text-fog-dark-text">Loading...</p>
    {:else if !rssEvent}
      <div class="rss-setup">
        <p class="mb-4 text-fog-text dark:text-fog-dark-text">
          You don't have an RSS feed subscription event yet. Create a kind {RSS_FEED_KIND} event to subscribe to external RSS feeds.
        </p>
        <p class="mb-4 text-sm text-fog-text-light dark:text-fog-dark-text-light">
          Add "u" tags with RSS feed URLs to subscribe to external feeds.
        </p>
        <button
          onclick={handleCreateRss}
          class="create-rss-button"
        >
          Create RSS Feed Subscription Event
        </button>
      </div>
    {:else}
      <div class="rss-content">
        <div class="rss-info">
          <h2 class="text-xl font-semibold mb-4 text-fog-text dark:text-fog-dark-text">Subscribed RSS Feeds</h2>
          {#if subscribedFeeds.length === 0}
            <p class="text-fog-text-light dark:text-fog-dark-text-light">
              No RSS feeds subscribed. Edit your kind {RSS_FEED_KIND} event to add "u" tags with RSS feed URLs.
            </p>
          {:else}
            <ul class="rss-feed-list">
              {#each subscribedFeeds as feedUrl}
                <li class="rss-feed-item">
                  <a
                    href={feedUrl}
                    target="_blank"
                    rel="noopener noreferrer"
                    class="rss-feed-link"
                  >
                    {feedUrl}
                  </a>
                  {#if feedErrors.has(feedUrl)}
                    <span class="feed-error">Error: {feedErrors.get(feedUrl)}</span>
                  {/if}
                </li>
              {/each}
            </ul>
          {/if}
          <div class="mt-6 pt-6 border-t border-fog-border dark:border-fog-dark-border">
            <p class="mb-2 text-sm text-fog-text dark:text-fog-dark-text">
              To add or remove feeds, edit your kind {RSS_FEED_KIND} event.
            </p>
            {#if rssEvent}
              <a
                href="/write"
                class="edit-rss-button"
                onclick={(e) => {
                  if (rssEvent) {
                    const cloneData = {
                      kind: rssEvent.kind,
                      content: rssEvent.content,
                      tags: rssEvent.tags,
                      isClone: false
                    };
                    sessionStorage.setItem('aitherboard_cloneEvent', JSON.stringify(cloneData));
                  }
                }}
              >
                Edit RSS Feed Event
              </a>
            {:else}
              <a
                href="/write?kind={RSS_FEED_KIND}"
                class="edit-rss-button"
              >
                Create RSS Feed Event
              </a>
            {/if}
          </div>
        </div>

        {#if subscribedFeeds.length > 0}
          <div class="rss-items-section">
            <h2 class="text-xl font-semibold mb-4 text-fog-text dark:text-fog-dark-text">RSS Feed Items</h2>
            {#if loadingFeeds}
              <p class="text-fog-text dark:text-fog-dark-text">Loading RSS feeds...</p>
            {:else if rssItems.length === 0}
              <p class="text-fog-text-light dark:text-fog-dark-text-light">No RSS items found.</p>
            {:else}
              <div class="rss-items-info mb-4">
                <p class="text-fog-text dark:text-fog-dark-text text-sm">
                  Showing {paginatedItems.length} of {rssItems.length} items
                </p>
              </div>
              
              {#if totalPages > 1}
                <div class="pagination pagination-top mb-4">
                  <button
                    class="pagination-button"
                    disabled={currentPage === 1}
                    onclick={() => {
                      if (currentPage > 1) currentPage--;
                    }}
                    aria-label="Previous page"
                  >
                    Previous
                  </button>
                  
                  <div class="pagination-info">
                    <span class="text-fog-text dark:text-fog-dark-text">
                      Page {currentPage} of {totalPages}
                    </span>
                  </div>
                  
                  <button
                    class="pagination-button"
                    disabled={currentPage === totalPages}
                    onclick={() => {
                      if (currentPage < totalPages) currentPage++;
                    }}
                    aria-label="Next page"
                  >
                    Next
                  </button>
                </div>
              {/if}
              
              <div class="rss-items">
                {#each paginatedItems as item (item.link + item.pubDate.getTime())}
                  <article class="rss-item">
                    <div class="rss-item-header">
                      <div class="rss-item-meta">
                        {#if item.feedTitle}
                          <span class="rss-feed-badge">{item.feedTitle}</span>
                        {/if}
                        <span class="rss-item-time">{getRelativeTime(item.pubDate)}</span>
                      </div>
                    </div>
                    <h3 class="rss-item-title">
                      <a
                        href={item.link}
                        target="_blank"
                        rel="noopener noreferrer"
                        class="rss-item-link"
                      >
                        {item.title}
                      </a>
                    </h3>
                    {#if item.description}
                      <div class="rss-item-description">
                        <MarkdownRenderer content={item.description} />
                      </div>
                    {/if}
                    {#if sessionManager.isLoggedIn()}
                      <div class="rss-item-actions flex items-center gap-2 mt-2">
                        <IconButton 
                          icon="message-square" 
                          label="Reply" 
                          size={16}
                          onclick={() => toggleReplyForm(item.link)}
                        />
                      </div>
                    {/if}
                    {#if openReplyFormFor === item.link}
                      <div class="rss-item-reply-form mt-4">
                        <RSSCommentForm 
                          url={item.link}
                          onPublished={() => {
                            openReplyFormFor = null;
                          }}
                          onCancel={() => {
                            openReplyFormFor = null;
                          }}
                        />
                      </div>
                    {/if}
                  </article>
                {/each}
              </div>
              
              {#if totalPages > 1}
                <div class="pagination pagination-bottom mt-4">
                  <button
                    class="pagination-button"
                    disabled={currentPage === 1}
                    onclick={() => {
                      if (currentPage > 1) currentPage--;
                    }}
                    aria-label="Previous page"
                  >
                    Previous
                  </button>
                  
                  <div class="pagination-info">
                    <span class="text-fog-text dark:text-fog-dark-text">
                      Page {currentPage} of {totalPages}
                    </span>
                  </div>
                  
                  <button
                    class="pagination-button"
                    disabled={currentPage === totalPages}
                    onclick={() => {
                      if (currentPage < totalPages) currentPage++;
                    }}
                    aria-label="Next page"
                  >
                    Next
                  </button>
                </div>
              {/if}
            {/if}
          </div>
        {/if}
      </div>
    {/if}
  </div>
</main>

<style>
  .rss-page {
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 0 1rem;
  }

  .rss-setup {
    padding: 2rem;
    background: var(--fog-post, #ffffff);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.5rem;
  }

  :global(.dark) .rss-setup {
    background: var(--fog-dark-post, #1f2937);
    border-color: var(--fog-dark-border, #374151);
  }


  .rss-info {
    padding: 2rem;
    background: var(--fog-post, #ffffff);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.5rem;
  }

  :global(.dark) .rss-info {
    background: var(--fog-dark-post, #1f2937);
    border-color: var(--fog-dark-border, #374151);
  }

  .rss-feed-list {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  .rss-feed-item {
    padding: 0.75rem;
    margin-bottom: 0.5rem;
    background: var(--fog-highlight, #f3f4f6);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.25rem;
  }

  :global(.dark) .rss-feed-item {
    background: var(--fog-dark-highlight, #374151);
    border-color: var(--fog-dark-border, #475569);
  }

  .rss-feed-link {
    color: var(--fog-accent, #64748b);
    text-decoration: none;
    word-break: break-all;
    font-size: 0.875rem;
  }

  :global(.dark) .rss-feed-link {
    color: var(--fog-dark-accent, #94a3b8);
  }

  .rss-feed-link:hover {
    text-decoration: underline;
  }

  .feed-error {
    display: block;
    margin-top: 0.5rem;
    color: var(--fog-danger, #dc2626);
    font-size: 0.75rem;
  }

  :global(.dark) .feed-error {
    color: var(--fog-dark-danger, #ef4444);
  }

  .rss-content {
    display: flex;
    flex-direction: column;
    gap: 2rem;
  }

  .rss-items-section {
    padding: 2rem;
    background: var(--fog-post, #ffffff);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.5rem;
  }

  :global(.dark) .rss-items-section {
    background: var(--fog-dark-post, #1f2937);
    border-color: var(--fog-dark-border, #374151);
  }

  .rss-items {
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }

  .rss-item {
    padding: 1rem;
    background: var(--fog-highlight, #f3f4f6);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.5rem;
  }

  :global(.dark) .rss-item {
    background: var(--fog-dark-highlight, #374151);
    border-color: var(--fog-dark-border, #475569);
  }

  .rss-item-header {
    margin-bottom: 0.5rem;
  }

  .rss-item-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
  }

  .rss-feed-badge {
    padding: 0.25rem 0.5rem;
    background: var(--fog-accent, #64748b);
    color: var(--fog-text, #f1f5f9);
    border-radius: 0.25rem;
    font-size: 0.75rem;
    font-weight: 500;
  }

  :global(.dark) .rss-feed-badge {
    background: var(--fog-dark-accent, #94a3b8);
  }

  .rss-item-time {
    font-size: 0.75rem;
    color: var(--fog-text-light, #52667a);
  }

  :global(.dark) .rss-item-time {
    color: var(--fog-dark-text-light, #a8b8d0);
  }

  .rss-item-title {
    margin: 0 0 0.5rem 0;
    font-size: 1.125rem;
    font-weight: 600;
  }

  .rss-item-link {
    color: var(--fog-text, #475569);
    text-decoration: none;
  }

  :global(.dark) .rss-item-link {
    color: var(--fog-dark-text, #cbd5e1);
  }

  .rss-item-link:hover {
    color: var(--fog-accent, #64748b);
    text-decoration: underline;
  }

  :global(.dark) .rss-item-link:hover {
    color: var(--fog-dark-accent, #94a3b8);
  }

  .rss-item-description {
    color: var(--fog-text, #475569);
    font-size: 0.875rem;
    line-height: 1.6;
  }

  :global(.dark) .rss-item-description {
    color: var(--fog-dark-text, #cbd5e1);
  }

  .rss-items-info {
    padding: 0.5rem 0;
  }

  .pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 1rem;
    margin-top: 2rem;
    margin-bottom: 2rem;
  }

  .pagination-top {
    margin-top: 0;
    margin-bottom: 1rem;
  }

  .pagination-bottom {
    margin-top: 2rem;
  }

  .pagination-button {
    padding: 0.5rem 1rem;
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.25rem;
    background: var(--fog-post, #ffffff);
    color: var(--fog-text, #1e293b);
    cursor: pointer;
    transition: all 0.2s;
  }

  .pagination-button:hover:not(:disabled) {
    background: var(--fog-highlight, #f1f5f9);
    border-color: var(--fog-accent, #94a3b8);
  }

  .pagination-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  :global(.dark) .pagination-button {
    background: var(--fog-dark-post, #1f2937);
    border-color: var(--fog-dark-border, #374151);
    color: var(--fog-dark-text, #f9fafb);
  }

  :global(.dark) .pagination-button:hover:not(:disabled) {
    background: var(--fog-dark-highlight, #475569);
    border-color: var(--fog-dark-accent, #64748b);
  }

  .pagination-info {
    min-width: 120px;
    text-align: center;
  }

</style>
