<script lang="ts">
  import ProfileBadge from '../../components/layout/ProfileBadge.svelte';
  import VoteCount from '../../components/content/VoteCount.svelte';
  import { nostrClient } from '../../services/nostr/nostr-client.js';
  import { relayManager } from '../../services/nostr/relay-manager.js';
  import { onMount } from 'svelte';
  import type { NostrEvent } from '../../types/nostr.js';
  import { getKindInfo, KIND } from '../../types/kind-lookup.js';
  import { stripMarkdown } from '../../services/text-utils.js';

  interface Props {
    thread: NostrEvent;
    commentCount?: number; // Pre-loaded comment count from batch fetch
    upvotes?: number; // Pre-calculated upvote count from batch fetch
    downvotes?: number; // Pre-calculated downvote count from batch fetch
    votesCalculated?: boolean; // Whether vote counts are ready to display
  }

  let { thread, commentCount: providedCommentCount = 0, upvotes: providedUpvotes = 0, downvotes: providedDownvotes = 0, votesCalculated: providedVotesCalculated = false }: Props = $props();

  let commentCount = $state(0);
  
  // Update comment count when provided value changes
  $effect(() => {
    commentCount = providedCommentCount;
  });
  let zapTotal = $state(0);
  let zapCount = $state(0);
  let latestResponseTime = $state<number | null>(null);
  let loadingStats = $state(true);
  let expanded = $state(false);
  let contentElement: HTMLElement | null = $state(null);
  let needsExpansion = $state(false);

  onMount(async () => {
    await loadStats();
  });

  $effect(() => {
    if (contentElement) {
      checkContentHeight();
      // Use ResizeObserver to detect when content changes (e.g., images loading)
      const observer = new ResizeObserver(() => {
        checkContentHeight();
      });
      observer.observe(contentElement);
      return () => observer.disconnect();
    }
  });

  function checkContentHeight() {
    if (contentElement) {
      // Use requestAnimationFrame to ensure DOM is fully updated
      requestAnimationFrame(() => {
        if (contentElement) {
          needsExpansion = contentElement.scrollHeight > 500;
        }
      });
    }
  }

  function toggleExpanded() {
    expanded = !expanded;
  }

  async function loadStats() {
    loadingStats = true;
    const timeout = 30000; // 30 seconds
    
    try {
      const config = nostrClient.getConfig();
      
      // Create a timeout promise
      const timeoutPromise = new Promise<never>((_, reject) => {
        setTimeout(() => reject(new Error('Stats loading timeout')), timeout);
      });
      
      // Race between loading and timeout
      await Promise.race([
        (async () => {
          // Vote counting is handled by DiscussionVoteButtons component - not needed here

          // Comment count is pre-loaded from batch fetch, skip individual loading
          // Only load comments if not provided (fallback for backwards compatibility)
          let commentEvents: NostrEvent[] = [];
          if (providedCommentCount === 0) {
            const commentRelays = relayManager.getCommentReadRelays();
            commentEvents = await nostrClient.fetchEvents(
              [{ kinds: [KIND.COMMENT], '#E': [thread.id], '#K': ['11'] }],
              commentRelays,
              { useCache: true }
            );
            commentCount = commentEvents.length;
          }

          // Load zap receipts (kind 9735)
          const zapRelays = relayManager.getZapReceiptReadRelays();
          const zapReceipts = await nostrClient.fetchEvents(
            [{ kinds: [KIND.ZAP_RECEIPT], '#e': [thread.id] }],
            zapRelays,
            { useCache: true }
          );
          
          // Calculate zap totals
          const threshold = config.zapThreshold;
          zapCount = 0;
          zapTotal = 0;
          for (const receipt of zapReceipts) {
            const amountTag = receipt.tags.find((t) => t[0] === 'amount');
            if (amountTag && amountTag[1]) {
              const amount = parseInt(amountTag[1], 10);
              if (!isNaN(amount) && amount >= threshold) {
                zapTotal += amount;
                zapCount++;
              }
            }
          }
          
          // Find latest response time (most recent comment or zap)
          // Note: Vote counting is handled by DiscussionVoteButtons, so we don't load reactions here
          let latestTime = thread.created_at;
          if (commentEvents.length > 0) {
            const latestComment = commentEvents.sort((a: NostrEvent, b: NostrEvent) => b.created_at - a.created_at)[0];
            latestTime = Math.max(latestTime, latestComment.created_at);
          }
          if (zapReceipts.length > 0) {
            const latestZap = zapReceipts.sort((a, b) => b.created_at - a.created_at)[0];
            latestTime = Math.max(latestTime, latestZap.created_at);
          }
          latestResponseTime = latestTime > thread.created_at ? latestTime : null;
        })(),
        timeoutPromise
      ]);
    } catch (error) {
      console.error('Error loading thread stats:', error);
      // On timeout or error, show zero stats instead of loading forever
      commentCount = 0;
      zapTotal = 0;
      zapCount = 0;
      latestResponseTime = null;
    } finally {
      loadingStats = false;
    }
  }

  function getTitle(): string {
    const titleTag = thread.tags.find((t) => t[0] === 'title');
    return titleTag?.[1] || 'Untitled';
  }

  function getTopics(): string[] {
    return thread.tags.filter((t) => t[0] === 't').map((t) => t[1]).slice(0, 3);
  }

  function getPreview(): string {
    // First 250 chars, plaintext (no markdown/images)
    const plaintext = stripMarkdown(thread.content);
    return plaintext.slice(0, 250) + (plaintext.length > 250 ? '...' : '');
  }

  function getRelativeTime(): string {
    const now = Math.floor(Date.now() / 1000);
    const diff = now - thread.created_at;
    const hours = Math.floor(diff / 3600);
    const days = Math.floor(diff / 86400);

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

  function getLatestResponseTime(): string {
    if (!latestResponseTime) return '';
    const now = Math.floor(Date.now() / 1000);
    const diff = now - latestResponseTime;
    const hours = Math.floor(diff / 3600);
    const days = Math.floor(diff / 86400);
    const minutes = Math.floor(diff / 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 getClientName(): string | null {
    const clientTag = thread.tags.find((t) => t[0] === 'client');
    return clientTag?.[1] || null;
  }
</script>

<article class="thread-card bg-fog-post dark:bg-fog-dark-post border border-fog-border dark:border-fog-dark-border p-4 mb-4 shadow-sm dark:shadow-lg">
  <a href="/event/{thread.id}" class="card-link">
    <div class="card-content" class:expanded bind:this={contentElement}>
      <div class="flex justify-between items-start mb-2">
        <h3 class="text-lg font-semibold">
          {getTitle()}
        </h3>
        <div class="flex items-center gap-2">
          <span class="text-sm text-fog-text-light dark:text-fog-dark-text-light">{getRelativeTime()}</span>
          <!-- Menu hidden in preview - not clickable in card preview -->
        </div>
      </div>

      <div class="mb-2 flex items-center gap-2">
        <div class="interactive-element">
          <ProfileBadge pubkey={thread.pubkey} />
        </div>
        {#if getClientName()}
          <span class="text-xs text-fog-text-light dark:text-fog-dark-text-light">via {getClientName()}</span>
        {/if}
      </div>

      <p class="text-sm mb-2">{getPreview()}</p>

      {#if getTopics().length > 0}
        <div class="flex gap-2 topic-tags">
          {#each getTopics() as topic}
            <span class="text-xs bg-fog-highlight dark:bg-fog-dark-highlight text-fog-text dark:text-fog-dark-text px-2 py-1 rounded">{topic}</span>
          {/each}
        </div>
      {/if}
    </div>
  </a>
  
  {#if needsExpansion}
    <button
      onclick={toggleExpanded}
      class="show-more-button text-sm text-fog-accent dark:text-fog-dark-accent hover:underline mt-2"
    >
      {expanded ? 'Show less' : 'Show more'}
    </button>
  {/if}

  <!-- Card footer (stats) - always visible, outside collapsible content -->
  <div class="flex items-center justify-between text-xs text-fog-text dark:text-fog-dark-text thread-stats">
    <div class="flex items-center gap-4 flex-wrap">
      {#if providedVotesCalculated}
        <VoteCount upvotes={providedUpvotes} downvotes={providedDownvotes} votesCalculated={true} size="xs" />
      {:else}
        <span class="text-fog-text-light dark:text-fog-dark-text-light">Loading votes...</span>
      {/if}
      {#if loadingStats}
        <span class="text-fog-text-light dark:text-fog-dark-text-light">Loading stats...</span>
      {:else}
        <span class="font-medium vote-comment-spacing">{commentCount} {commentCount === 1 ? 'comment' : 'comments'}</span>
        {#if latestResponseTime}
          <span class="text-fog-text-light dark:text-fog-dark-text-light">Last: {getLatestResponseTime()}</span>
        {/if}
        {#if zapCount > 0}
          <span class="font-medium">⚡ {zapTotal.toLocaleString()} sats ({zapCount})</span>
        {/if}
      {/if}
    </div>
  </div>
  
  <div class="kind-badge">
    <span class="kind-number">{getKindInfo(thread.kind).number}</span>
    <span class="kind-description">{getKindInfo(thread.kind).description}</span>
  </div>
</article>

<style>
  .thread-card {
    max-width: var(--content-width);
    position: relative;
  }

  .card-link {
    display: block;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
  }

  .card-link:hover {
    background: var(--fog-highlight, #f3f4f6);
  }

  :global(.dark) .card-link:hover {
    background: var(--fog-dark-highlight, #475569);
  }

  .interactive-element {
    position: relative;
    z-index: 10;
    pointer-events: auto;
  }

  .card-link {
    pointer-events: auto;
  }

  .card-link > * {
    pointer-events: none;
  }

  .card-link .interactive-element {
    pointer-events: auto;
  }

  .thread-card a {
    color: inherit;
    text-decoration: none;
  }

  .thread-card a:hover {
    text-decoration: none;
  }

  .card-content {
    max-height: 500px;
    overflow: hidden;
    transition: max-height 0.3s ease;
    /* Ensure footer below is not affected by overflow */
    position: relative;
  }

  .card-content.expanded {
    max-height: none;
  }

  .show-more-button {
    width: 100%;
    text-align: center;
    padding: 0.5rem;
    background: transparent;
    border: none;
    cursor: pointer;
  }

  .kind-badge {
    position: absolute;
    bottom: 0.5rem;
    right: 0.5rem;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.625rem;
    line-height: 1;
    color: var(--fog-text-light, #9ca3af);
    white-space: nowrap;
  }

  .topic-tags {
    margin-bottom: 1rem; /* Increased space between topic tags and count row */
  }

  @media (max-width: 640px) {
    .topic-tags {
      margin-bottom: 1.25rem; /* Even more space on narrow screens */
    }
    
    .kind-badge {
      position: static;
      margin-top: 0.25rem; /* Decreased space between count row and kind badge */
      justify-content: flex-end;
    }
    
    .thread-stats {
      margin-bottom: 0.25rem; /* Decreased space between count row and kind badge */
    }
  }

  :global(.dark) .kind-badge {
    color: var(--fog-dark-text-light, #6b7280);
  }

  .kind-number {
    font-weight: 600;
  }

  .kind-description {
    font-size: 0.625rem;
    opacity: 0.8;
  }

  .thread-stats {
    padding-right: 0;
    margin-bottom: 1.5rem; /* Space for kind badge below */
    padding-top: 0.5rem;
    border-top: 1px solid var(--fog-border, #e5e7eb);
    margin-top: 0.5rem;
    /* Ensure footer is always visible, even when content is collapsed */
    position: relative;
    z-index: 1;
    overflow: visible;
  }

  :global(.dark) .thread-stats {
    border-top-color: var(--fog-dark-border, #374151);
  }

</style>
