<script lang="ts">
  import ProfileBadge from '../../components/layout/ProfileBadge.svelte';
  import EventMenu from '../../components/EventMenu.svelte';
  import MarkdownRenderer from '../../components/content/MarkdownRenderer.svelte';
  import MediaAttachments from '../../components/content/MediaAttachments.svelte';
  import MetadataCard from '../../components/content/MetadataCard.svelte';
  import ReplyContext from '../../components/content/ReplyContext.svelte';
  import QuotedContext from '../../components/content/QuotedContext.svelte';
  import FeedReactionButtons from '../reactions/FeedReactionButtons.svelte';
  import MediaViewer from '../../components/content/MediaViewer.svelte';
  import CommentForm from '../comments/CommentForm.svelte';
  import type { NostrEvent } from '../../types/nostr.js';
  import { getKindInfo, KIND } from '../../types/kind-lookup.js';
  import { stripMarkdown } from '../../services/text-utils.js';
  import { isBookmarked } from '../../services/user-actions.js';
  import { sessionManager } from '../../services/auth/session-manager.js';
  import { findNIP21Links, parseNIP21 } from '../../services/nostr/nip21-parser.js';
  import { nip19 } from 'nostr-tools';
  import { onMount } from 'svelte';

  interface Props {
    post: NostrEvent;
    fullView?: boolean; // If true, show full content (markdown, media, profile pics, reactions)
    preloadedReactions?: NostrEvent[]; // Pre-loaded reactions to avoid duplicate fetches
    parentEvent?: NostrEvent; // Optional parent event if already loaded
    quotedEvent?: NostrEvent; // Optional quoted event if already loaded
  }

  let { post, fullView = false, preloadedReactions, parentEvent: providedParentEvent, quotedEvent: providedQuotedEvent }: Props = $props();
  
  // Check if this event is bookmarked (async, so we use state)
  // Only check if user is logged in
  let bookmarked = $state(false);
  const isLoggedIn = $derived(sessionManager.isLoggedIn());
  
  // Collapse state for feed view
  let isExpanded = $state(false);
  let shouldCollapse = $state(false);
  let cardElement: HTMLElement | null = $state(null);
  let contentElement: HTMLElement | null = $state(null);
  
  // Reply state
  let showReplyForm = $state(false);
  
  // Check if card should be collapsed (only in feed view)
  let isMounted = $state(true);
  
  $effect(() => {
    if (fullView) {
      shouldCollapse = false;
      return;
    }
    
    isMounted = true;
    
    // Wait for content to render, then check height
    let timeoutId: ReturnType<typeof setTimeout> | null = null;
    let rafId1: number | null = null;
    let rafId2: number | null = null;
    
    const checkHeight = () => {
      if (!isMounted || !cardElement) return;
      
      // Measure the full card height (using scrollHeight to get full content height)
      const cardHeight = cardElement.scrollHeight;
      shouldCollapse = cardHeight > 500;
    };
    
    // Check after content is rendered
    timeoutId = setTimeout(() => {
      if (!isMounted) return;
      rafId1 = requestAnimationFrame(() => {
        if (!isMounted) return;
        rafId2 = requestAnimationFrame(checkHeight);
      });
    }, 200);
    
    return () => {
      isMounted = false;
      if (timeoutId) clearTimeout(timeoutId);
      if (rafId1) cancelAnimationFrame(rafId1);
      if (rafId2) cancelAnimationFrame(rafId2);
    };
  });
  
  function toggleExpand() {
    isExpanded = !isExpanded;
  }
  
  $effect(() => {
    let cancelled = false;
    
    if (isLoggedIn) {
      isBookmarked(post.id).then(b => {
        if (!cancelled) {
        bookmarked = b;
        }
      });
    } else {
      bookmarked = false;
    }
    
    return () => {
      cancelled = true;
    };
  });

  function getRelativeTime(): string {
    const now = Math.floor(Date.now() / 1000);
    const diff = now - post.created_at;
    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 = post.tags.find((t) => t[0] === 'client');
    return clientTag?.[1] || null;
  }

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

  function getPlaintextContent(): string {
    // Plaintext only (no markdown/images) - keep full length
    return stripMarkdown(post.content);
  }

  // Parse NIP-21 links and create segments for rendering
  interface ContentSegment {
    type: 'text' | 'profile' | 'event' | 'url' | 'wikilink' | 'hashtag';
    content: string; // Display text (without nostr: prefix for links)
    pubkey?: string; // For profile badges
    eventId?: string; // For event links (bech32 or hex)
    url?: string; // For regular HTTP/HTTPS URLs
    wikilink?: string; // For wikilink d-tag
    hashtag?: string; // For hashtag topic name
  }

  function parseContentWithNIP21Links(): ContentSegment[] {
    const plaintext = getPlaintextContent();
    const links = findNIP21Links(plaintext);
    const segments: ContentSegment[] = [];
    
    let lastIndex = 0;
    
    for (const link of links) {
      // Add text before the link
      if (link.start > lastIndex) {
        segments.push({
          type: 'text',
          content: plaintext.slice(lastIndex, link.start)
        });
      }
      
      // Add the link as appropriate segment
      if (link.parsed.type === 'npub' || link.parsed.type === 'nprofile') {
        // Extract pubkey from bech32
        let pubkey: string | null = null;
        try {
          const decoded = nip19.decode(link.parsed.data);
          if (decoded.type === 'npub') {
            pubkey = decoded.data as string;
          } else if (decoded.type === 'nprofile') {
            pubkey = (decoded.data as any).pubkey;
          }
        } catch (e) {
          // If decoding fails, just show as text
          segments.push({
            type: 'text',
            content: link.uri
          });
          lastIndex = link.end;
          continue;
        }
        
        if (pubkey) {
          segments.push({
            type: 'profile',
            content: link.uri,
            pubkey
          });
        } else {
          segments.push({
            type: 'text',
            content: link.uri
          });
        }
      } else if (link.parsed.type === 'nevent' || link.parsed.type === 'naddr' || link.parsed.type === 'note' || link.parsed.type === 'hexID') {
        // Event link - use bech32 string or hex ID
        const eventId = link.parsed.type === 'hexID' ? link.parsed.data : link.parsed.data;
        // Display without "nostr:" prefix
        const displayText = link.parsed.data;
        segments.push({
          type: 'event',
          content: displayText,
          eventId
        });
      } else {
        // Unknown type, show as text
        segments.push({
          type: 'text',
          content: link.uri
        });
      }
      
      lastIndex = link.end;
    }
    
    // Add remaining text
    if (lastIndex < plaintext.length) {
      segments.push({
        type: 'text',
        content: plaintext.slice(lastIndex)
      });
    }
    
    // If no links found, return single text segment
    if (segments.length === 0) {
      segments.push({
        type: 'text',
        content: plaintext
      });
    }
    
    // Normalize d-tag according to NIP-54
    function normalizeDTag(text: string): string {
      let normalized = text;
      
      // Convert to lowercase (preserving non-ASCII characters)
      normalized = normalized.toLowerCase();
      
      // Convert whitespace to `-`
      normalized = normalized.replace(/\s+/g, '-');
      
      // Remove punctuation and symbols (but preserve non-ASCII letters and numbers)
      normalized = normalized.replace(/[^\p{L}\p{N}-]/gu, '');
      
      // Collapse multiple consecutive `-` to a single `-`
      normalized = normalized.replace(/-+/g, '-');
      
      // Remove leading and trailing `-`
      normalized = normalized.replace(/^-+|-+$/g, '');
      
      return normalized;
    }

    // Now parse wikilinks [[wikilink]], hashtags #topic, and regular HTTP/HTTPS URLs from text segments
    const finalSegments: ContentSegment[] = [];
    // Match [[target]] or [[target|display text]]
    const wikilinkRegex = /\[\[([^\]]+)\]\]/g;
    // Match hashtags: # followed by word characters, but not if it's part of a URL
    const hashtagRegex = /#([\p{L}\p{N}_]+)/gu;
    const urlRegex = /(https?:\/\/[^\s<>"{}|\\^`\[\]]+)/gi;
    
    for (const segment of segments) {
      if (segment.type === 'text') {
        let textIndex = 0;
        let match;
        const text = segment.content;
        
        // First, parse wikilinks according to NIP-54
        const wikilinkMatches: Array<{ index: number; length: number; dTag: string; displayText: string }> = [];
        while ((match = wikilinkRegex.exec(text)) !== null) {
          const content = match[1];
          // Check if it has pipe syntax: [[target|display]]
          const pipeIndex = content.indexOf('|');
          let targetText: string;
          let displayText: string;
          
          if (pipeIndex !== -1) {
            targetText = content.slice(0, pipeIndex).trim();
            displayText = content.slice(pipeIndex + 1).trim();
          } else {
            targetText = content.trim();
            displayText = content.trim();
          }
          
          // Normalize the d-tag using the function defined above
          const normalizedDTag = normalizeDTag(targetText);
          
          wikilinkMatches.push({
            index: match.index,
            length: match[0].length,
            dTag: normalizedDTag,
            displayText: displayText
          });
        }
        
        // Then parse hashtags
        const hashtagMatches: Array<{ index: number; length: number; hashtag: string }> = [];
        hashtagRegex.lastIndex = 0; // Reset regex
        while ((match = hashtagRegex.exec(text)) !== null) {
          hashtagMatches.push({
            index: match.index,
            length: match[0].length,
            hashtag: match[1]
          });
        }
        
        // Then parse URLs
        const urlMatches: Array<{ index: number; length: number; url: string }> = [];
        urlRegex.lastIndex = 0; // Reset regex
        while ((match = urlRegex.exec(text)) !== null) {
          urlMatches.push({
            index: match.index,
            length: match[0].length,
            url: match[1]
          });
        }
        
        // Merge and sort all matches by index
        const allMatches = [
          ...wikilinkMatches.map(m => ({ ...m, type: 'wikilink' as const })),
          ...hashtagMatches.map(m => ({ ...m, type: 'hashtag' as const })),
          ...urlMatches.map(m => ({ ...m, type: 'url' as const }))
        ].sort((a, b) => a.index - b.index);
        
        // Filter out hashtags that are inside URLs or wikilinks
        const filteredMatches = allMatches.filter((match, idx) => {
          if (match.type === 'hashtag') {
            // Check if this hashtag is inside any URL
            const insideUrl = urlMatches.some(urlMatch => 
              match.index >= urlMatch.index && 
              match.index < urlMatch.index + urlMatch.length
            );
            if (insideUrl) return false;
            
            // Check if this hashtag is inside any wikilink
            const insideWikilink = wikilinkMatches.some(wikilinkMatch => 
              match.index >= wikilinkMatch.index && 
              match.index < wikilinkMatch.index + wikilinkMatch.length
            );
            if (insideWikilink) return false;
            
            return true;
          }
          return true;
        });
        
        // Process matches in order
        for (const match of filteredMatches) {
          // Add text before the match
          if (match.index > textIndex) {
            finalSegments.push({
              type: 'text',
              content: text.slice(textIndex, match.index)
            });
          }
          
          // Add the match
          if (match.type === 'wikilink') {
            const wikilinkMatch = match as typeof wikilinkMatches[0] & { type: 'wikilink' };
            finalSegments.push({
              type: 'wikilink',
              content: wikilinkMatch.displayText || wikilinkMatch.dTag,
              wikilink: wikilinkMatch.dTag
            });
          } else if (match.type === 'hashtag') {
            const hashtagMatch = match as typeof hashtagMatches[0] & { type: 'hashtag' };
            finalSegments.push({
              type: 'hashtag',
              content: `#${hashtagMatch.hashtag}`,
              hashtag: hashtagMatch.hashtag
            });
          } else {
            finalSegments.push({
              type: 'url',
              content: match.url,
              url: match.url
            });
          }
          
          textIndex = match.index + match.length;
        }
        
        // Add remaining text after last match
        if (textIndex < text.length) {
          finalSegments.push({
            type: 'text',
            content: text.slice(textIndex)
          });
        }
      } else {
        // Keep non-text segments as-is
        finalSegments.push(segment);
      }
    }
    
    return finalSegments.length > 0 ? finalSegments : segments;
  }


  function getEventUrl(eventId: string): string {
    // Decode bech32 or use hex directly to get the event ID
    try {
      if (eventId.length === 64 && /^[a-f0-9]{64}$/i.test(eventId)) {
        // Already hex - use it directly
        return `/event/${eventId}`;
      } else {
        // Try to decode bech32
        const decoded = nip19.decode(eventId);
        if (decoded.type === 'note' || decoded.type === 'nevent') {
          const id = decoded.type === 'note' ? String(decoded.data) : (decoded.data && typeof decoded.data === 'object' && 'id' in decoded.data ? String(decoded.data.id) : eventId);
          return `/event/${id}`;
        } else if (decoded.type === 'naddr') {
          // For naddr, use the bech32 string in the URL
          return `/event/${eventId}`;
        } else {
          return `/event/${eventId}`;
        }
      }
    } catch (decodeError) {
      // If decoding fails, use the ID as-is
      return `/event/${eventId}`;
    }
  }

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

  function isReply(): boolean {
    return post.tags.some((t) => t[0] === 'e' && t[1] !== post.id);
  }

  function getReplyEventId(): string | null {
    const replyTag = post.tags.find((t) => t[0] === 'e' && t[3] === 'reply');
    if (replyTag) return replyTag[1];
    const rootId = getRootEventId();
    const eTag = post.tags.find((t) => t[0] === 'e' && t[1] !== rootId && t[1] !== post.id);
    return eTag?.[1] || null;
  }

  function getRootEventId(): string | null {
    const rootTag = post.tags.find((t) => t[0] === 'root');
    return rootTag?.[1] || null;
  }

  function hasQuotedEvent(): boolean {
    return post.tags.some((t) => t[0] === 'q');
  }

  function getQuotedEventId(): string | null {
    const quotedTag = post.tags.find((t) => t[0] === 'q');
    return quotedTag?.[1] || null;
  }

  // Check if URL appears in content (as plain URL or in markdown)
  function isUrlInContent(url: string): boolean {
    const normalized = normalizeUrl(url);
    const content = post.content.toLowerCase();
    
    // Check if URL appears as plain text (with or without protocol)
    const urlWithoutProtocol = normalized.replace(/^https?:\/\//i, '');
    if (content.includes(normalized.toLowerCase()) || content.includes(urlWithoutProtocol.toLowerCase())) {
      return true;
  }

    // Check if URL appears in markdown image syntax ![alt](url)
    const markdownImageRegex = /!\[.*?\]\((.*?)\)/gi;
    let match;
    while ((match = markdownImageRegex.exec(post.content)) !== null) {
      const markdownUrl = normalizeUrl(match[1]);
      if (markdownUrl === normalized) {
        return true;
  }
    }
    
    // Check if URL appears in HTML img/video/audio tags
    const htmlTagRegex = /<(img|video|audio)[^>]+src=["']([^"']+)["']/gi;
    while ((match = htmlTagRegex.exec(post.content)) !== null) {
      const htmlUrl = normalizeUrl(match[2]);
      if (htmlUrl === normalized) {
        return true;
    }
    }
    
    return false;
  }

  function normalizeUrl(url: string): string {
    try {
      const parsed = new URL(url);
      return `${parsed.protocol}//${parsed.host}${parsed.pathname}`.replace(/\/$/, '');
    } catch {
      return url;
    }
    }
    
  // Extract media URLs from event tags (image, imeta, file) - for feed view only
  // Excludes URLs that are already in the content
  function getMediaUrls(): string[] {
    const urls: string[] = [];
    const seen = new Set<string>();
    
    // 1. Image tag (NIP-23)
    const imageTag = post.tags.find((t) => t[0] === 'image');
    if (imageTag && imageTag[1]) {
      const normalized = normalizeUrl(imageTag[1]);
      if (!seen.has(normalized) && !isUrlInContent(imageTag[1])) {
        urls.push(imageTag[1]);
        seen.add(normalized);
      }
  }

    // 2. imeta tags (NIP-92)
    for (const tag of post.tags) {
      if (tag[0] === 'imeta') {
        for (let i = 1; i < tag.length; i++) {
          const item = tag[i];
          if (item.startsWith('url ')) {
            const url = item.substring(4).trim();
            const normalized = normalizeUrl(url);
            if (!seen.has(normalized) && !isUrlInContent(url)) {
              urls.push(url);
              seen.add(normalized);
            }
            break;
          }
        }
      }
    }

    // 3. file tags (NIP-94)
    for (const tag of post.tags) {
      if (tag[0] === 'file' && tag[1]) {
        const normalized = normalizeUrl(tag[1]);
        if (!seen.has(normalized) && !isUrlInContent(tag[1])) {
          urls.push(tag[1]);
          seen.add(normalized);
      }
      }
    }

    return urls;
  }


  // Media viewer state
  let mediaViewerOpen = $state(false);
  let mediaViewerUrl = $state<string | null>(null);

  function handleMediaUrlClick(e: MouseEvent, url: string) {
    e.stopPropagation(); // Don't open drawer when clicking media URL
    e.preventDefault();
    mediaViewerUrl = url;
    mediaViewerOpen = true;
  }

  function closeMediaViewer() {
    mediaViewerOpen = false;
    mediaViewerUrl = null;
  }

</script>

<article 
  bind:this={cardElement}
  class="Feed-post" 
  data-post-id={post.id} 
  id="event-{post.id}" 
  data-event-id={post.id}
  class:collapsed={!fullView && shouldCollapse && !isExpanded}
>
  {#if fullView}
    <!-- Full view: show complete content with markdown, media, profile pics, reactions -->
    {#if isReply()}
      <ReplyContext 
        parentEvent={providedParentEvent || undefined} 
        parentEventId={getReplyEventId() || undefined}
        targetId={providedParentEvent ? `event-${providedParentEvent.id}` : undefined}
      />
    {/if}

    {#if hasQuotedEvent()}
      <QuotedContext 
        quotedEvent={providedQuotedEvent}
        quotedEventId={getQuotedEventId() || undefined}
        targetId={providedQuotedEvent ? `event-${providedQuotedEvent.id}` : undefined}
      />
    {/if}

    <MetadataCard event={post} hideTitle={true} hideImageIfInMedia={true} />

      {@const title = getTitle()}
      {#if title && title !== 'Untitled'}
      <h2 class="post-title font-bold mb-4 text-fog-text dark:text-fog-dark-text" style="font-size: 1.5em;">
          {title}
        </h2>
    {/if}

    <div class="post-header flex flex-col gap-2 mb-2">
      <div class="flex items-center justify-end gap-2 flex-nowrap">
        <div class="post-header-actions flex items-center gap-2 flex-shrink-0">
          {#if isLoggedIn && bookmarked}
            <span class="bookmark-indicator bookmarked" title="Bookmarked">🔖</span>
          {/if}
          <EventMenu event={post} showContentActions={true} />
        </div>
      </div>
      <div class="flex items-center gap-2 flex-nowrap">
        <div class="flex-shrink-1 min-w-0">
      <ProfileBadge pubkey={post.pubkey} />
        </div>
        <span class="text-fog-text-light dark:text-fog-dark-text-light flex-shrink-0 whitespace-nowrap" style="font-size: 0.75em;">{getRelativeTime()}</span>
      {#if getClientName()}
          <span class="text-fog-text-light dark:text-fog-dark-text-light flex-shrink-0" style="font-size: 0.75em;">via {getClientName()}</span>
      {/if}
      {#if post.kind === KIND.DISCUSSION_THREAD}
          {@const topics = getTopics()}
        {#if topics.length === 0}
            <a href="/topics/General" class="topic-badge px-2 py-0.5 rounded bg-fog-border dark:bg-fog-dark-border text-fog-text-light dark:text-fog-dark-text-light hover:underline" style="font-size: 0.75em;">General</a>
        {:else}
          {#each topics.slice(0, 3) as topic}
              <a href="/topics/{topic}" class="topic-badge px-2 py-0.5 rounded bg-fog-border dark:bg-fog-dark-border text-fog-text-light dark:text-fog-dark-text-light hover:underline" style="font-size: 0.75em;">{topic}</a>
          {/each}
        {/if}
        {/if}
      </div>
      <hr class="post-header-divider" />
    </div>

    <div class="post-content mb-2">
      <MediaAttachments event={post} />
      <MarkdownRenderer content={post.content} event={post} />
    </div>

    <div class="post-actions flex flex-wrap items-center gap-2 sm:gap-4">
      <FeedReactionButtons event={post} preloadedReactions={preloadedReactions} />
    </div>
        {:else}
    <!-- Feed view: plaintext only, no profile pics, media as URLs -->
    <div class="post-header flex flex-col gap-2 mb-2">
      <div class="flex items-center gap-2 flex-nowrap">
        <div class="flex-shrink-1 min-w-0">
          <ProfileBadge pubkey={post.pubkey} inline={true} />
        </div>
        <span class="text-fog-text-light dark:text-fog-dark-text-light flex-shrink-0 whitespace-nowrap" style="font-size: 0.75em;">{getRelativeTime()}</span>
        {#if getClientName()}
          <span class="text-fog-text-light dark:text-fog-dark-text-light flex-shrink-0" style="font-size: 0.75em;">via {getClientName()}</span>
        {/if}
        {#if post.kind === KIND.DISCUSSION_THREAD}
          {@const topics = getTopics()}
          {#if topics.length === 0}
            <a href="/topics/General" class="topic-badge px-2 py-0.5 rounded bg-fog-border dark:bg-fog-dark-border text-fog-text-light dark:text-fog-dark-text-light hover:underline" style="font-size: 0.75em;">General</a>
            {:else}
            {#each topics.slice(0, 3) as topic}
              <a href="/topics/{topic}" class="topic-badge px-2 py-0.5 rounded bg-fog-border dark:bg-fog-dark-border text-fog-text-light dark:text-fog-dark-text-light hover:underline" style="font-size: 0.75em;">{topic}</a>
            {/each}
          {/if}
        {/if}
      </div>
      <hr class="post-header-divider" />
    </div>

    {@const title = getTitle()}
    {#if title && title !== 'Untitled'}
      <h2 class="post-title font-bold mb-2 text-fog-text dark:text-fog-dark-text" style="font-size: 1.5em;">
        {title}
      </h2>
    {/if}

    <div bind:this={contentElement} class="post-content mb-2" class:collapsed-content={!fullView && shouldCollapse && !isExpanded}>
      <p class="text-fog-text dark:text-fog-dark-text whitespace-pre-wrap word-wrap">
        {#each parseContentWithNIP21Links() as segment}
          {#if segment.type === 'text'}
            {segment.content}
          {:else if segment.type === 'profile' && segment.pubkey}
            <ProfileBadge pubkey={segment.pubkey} inline={true} />
          {:else if segment.type === 'event' && segment.eventId}
            <a
              href={getEventUrl(segment.eventId)}
              target="_blank"
              rel="noopener noreferrer"
              class="nostr-event-link text-fog-accent dark:text-fog-dark-accent hover:underline"
            >
              {segment.content}
            </a>
          {:else if segment.type === 'url' && segment.url}
            {@const isMediaUrl = /\.(jpg|jpeg|png|gif|webp|svg|bmp|mp4|webm|ogg|mov|avi|mkv|mp3|wav|ogg|flac|aac|m4a)(\?|#|$)/i.test(segment.url)}
            {#if isMediaUrl}
              <button
                type="button"
                class="text-fog-accent dark:text-fog-dark-accent hover:underline bg-transparent border-none p-0 cursor-pointer"
                onclick={(e) => handleMediaUrlClick(e, segment.url!)}
              >
                {segment.content}
              </button>
            {:else}
              <a
                href={segment.url}
                target="_blank"
                rel="noopener noreferrer"
                class="text-fog-accent dark:text-fog-dark-accent hover:underline"
                onclick={(e) => e.stopPropagation()}
              >
                {segment.content}
              </a>
            {/if}
          {:else if segment.type === 'wikilink' && segment.wikilink}
            <a
              href="/replaceable/{segment.wikilink}"
              class="text-fog-accent dark:text-fog-dark-accent hover:underline"
              onclick={(e) => e.stopPropagation()}
            >
              {segment.content}
            </a>
          {:else if segment.type === 'hashtag' && segment.hashtag}
            <a
              href="/topics/{segment.hashtag}"
              class="text-fog-accent dark:text-fog-dark-accent hover:underline"
              onclick={(e) => e.stopPropagation()}
            >
              {segment.content}
            </a>
          {/if}
        {/each}
      </p>
      
      {#if getMediaUrls().length > 0}
        {@const mediaUrls = getMediaUrls()}
        <div class="media-urls mt-2">
          {#each mediaUrls as url}
            <button
              type="button"
              onclick={(e) => handleMediaUrlClick(e, url)}
              class="media-url-link text-fog-accent dark:text-fog-dark-accent hover:underline break-all bg-transparent border-none p-0 cursor-pointer text-left"
              style="font-size: 0.875em;"
            >
              {url}
            </button>
          {/each}
          </div>
      {/if}
  </div>
  
    {#if !fullView && shouldCollapse}
      <div class="show-more-container">
    <button 
      onclick={toggleExpand}
          class="show-more-btn text-fog-accent dark:text-fog-dark-accent hover:underline"
          style="font-size: 0.875em;"
    >
          {isExpanded ? 'Show Less' : 'Show More'}
    </button>
      </div>
  {/if}

    {#if !fullView}
      <div class="feed-card-footer flex items-center justify-between">
        <div class="feed-card-actions flex items-center gap-2">
          {#if isLoggedIn && bookmarked}
            <span class="bookmark-indicator bookmarked" title="Bookmarked">🔖</span>
          {/if}
          <EventMenu event={post} showContentActions={true} />
        </div>
        <div class="kind-badge feed-card-kind-badge">
          <span class="kind-number">{getKindInfo(post.kind).number}</span>
          <span class="kind-description">{getKindInfo(post.kind).description}</span>
        </div>
      </div>
    {/if}
  {/if}
  
  {#if fullView}
  <div class="kind-badge">
    <span class="kind-number">{getKindInfo(post.kind).number}</span>
    <span class="kind-description">{getKindInfo(post.kind).description}</span>
  </div>
  {/if}
</article>

{#if isLoggedIn}
  <div class="reply-section mb-2">
    <button
      onclick={() => showReplyForm = !showReplyForm}
      class="reply-btn text-fog-accent dark:text-fog-dark-accent hover:underline"
      style="font-size: 0.875em;"
    >
      Reply
    </button>
  </div>
  
  {#if showReplyForm}
    <div class="reply-form-container mb-4">
      <CommentForm
        threadId={post.id}
        rootEvent={post}
        onPublished={() => {
          showReplyForm = false;
        }}
        onCancel={() => {
          showReplyForm = false;
        }}
      />
    </div>
  {/if}
{/if}

{#if mediaViewerUrl && mediaViewerOpen}
  <MediaViewer url={mediaViewerUrl} isOpen={mediaViewerOpen} onClose={closeMediaViewer} />
{/if}

<style>
  .Feed-post {
    padding: 1rem;
    margin-bottom: 1rem;
    background: var(--fog-post, #ffffff);
    border: 1px solid var(--fog-border, #e5e7eb);
    border-radius: 0.25rem;
    position: relative;
  }
  
  .Feed-post.collapsed {
    max-height: 500px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  
  .Feed-post.collapsed .post-content.collapsed-content {
    flex: 1;
    min-height: 0;
  }

  :global(.dark) .Feed-post {
    background: var(--fog-dark-post, #1f2937);
    border-color: var(--fog-dark-border, #374151);
  }
  
  .post-content.collapsed-content {
    max-height: 350px;
    overflow: hidden;
    position: relative;
  }
  
  .post-content.collapsed-content::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: linear-gradient(to bottom, transparent, var(--fog-post, #ffffff));
    pointer-events: none;
  }
  
  :global(.dark) .post-content.collapsed-content::after {
    background: linear-gradient(to bottom, transparent, var(--fog-dark-post, #1f2937));
  }
  
  .show-more-container {
    text-align: center;
    padding: 0.5rem 0;
  }
  
  .show-more-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    font-weight: 500;
  }

  .post-content {
    line-height: 1.6;
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  .word-wrap {
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  .media-urls {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }

  .media-url-link {
    word-break: break-all;
  }

  .nostr-event-link {
    word-break: break-all;
    text-decoration: underline;
  }

  .nostr-event-link:hover {
    text-decoration: underline;
  }

  .post-actions {
    padding-top: 0.5rem;
    padding-right: 6rem;
    border-top: 1px solid var(--fog-border, #e5e7eb);
    margin-top: 0.5rem;
  }

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

  .feed-card-footer {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--fog-border, #e5e7eb);
    flex-shrink: 0;
  }

  :global(.dark) .feed-card-footer {
    border-top-color: var(--fog-dark-border, #374151);
  }

  .feed-card-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
  }

  .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);
  }

  .feed-card-kind-badge {
    position: static;
  }

  :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;
  }

  .Feed-post {
    position: relative;
  }


  .post-header {
    display: flex;
    align-items: center;
    line-height: 1.5;
  }

  .post-header-actions {
    flex-shrink: 0;
  }

  .post-header-divider {
    margin: 0 0 0.5rem 0;
    border: none;
    border-top: 1px solid var(--fog-border, #e5e7eb);
    width: 100%;
  }

  :global(.dark) .post-header-divider {
    border-top-color: var(--fog-dark-border, #374151);
  }

  .post-header :global(.profile-badge) {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    line-height: 1.5;
    width: auto;
    max-width: none;
  }


  .post-header :global(.profile-badge span) {
    line-height: 1.5;
    vertical-align: middle;
  }

  .bookmark-indicator {
    display: inline-block;
    font-size: 1rem;
    line-height: 1;
    filter: grayscale(100%);
    transition: filter 0.2s;
  }

  .bookmark-indicator.bookmarked {
    filter: grayscale(0%);
  }

</style>
