<script lang="ts">
  import * as marked from 'marked';
  import { sanitizeMarkdown } from '../../services/security/sanitizer.js';
  import { findNIP21Links } from '../../services/nostr/nip21-parser.js';
  import { nip19 } from 'nostr-tools';
  import { onMount, tick } from 'svelte';
  import ProfileBadge from '../layout/ProfileBadge.svelte';
  import EmbeddedEvent from './EmbeddedEvent.svelte';
  import { mountComponent } from './mount-component-action.js';

  interface Props {
    content?: string;
  }

  let { content = '' }: Props = $props();

  let rendered = $state('');
  let containerElement: HTMLDivElement | null = $state(null);
  
  // Track profile badges and embedded events to render
  let profileBadges = $state<Map<string, string>>(new Map()); // placeholder -> pubkey
  let embeddedEvents = $state<Map<string, string>>(new Map()); // placeholder -> eventId
  
  // Process placeholder divs after HTML is rendered and mount components
  $effect(() => {
    if (!containerElement || !rendered) return;
    
    tick().then(() => {
      if (!containerElement) return;
      
      // Mount profile badge components
      const badgeElements = containerElement.querySelectorAll('.nostr-profile-badge-placeholder');
      badgeElements.forEach((el) => {
        const pubkey = el.getAttribute('data-pubkey');
        const placeholder = el.getAttribute('data-placeholder');
        if (pubkey && placeholder && profileBadges.has(placeholder)) {
          // Don't clear if already mounted
          if (el.children.length === 0) {
            mountComponent(el as HTMLElement, ProfileBadge as any, { pubkey });
          }
        }
      });
      
      // Mount embedded event components
      const eventElements = containerElement.querySelectorAll('.nostr-embedded-event-placeholder');
      eventElements.forEach((el) => {
        const eventId = el.getAttribute('data-event-id');
        const placeholder = el.getAttribute('data-placeholder');
        if (eventId && placeholder && embeddedEvents.has(placeholder)) {
          // Don't clear if already mounted
          if (el.children.length === 0) {
            mountComponent(el as HTMLElement, EmbeddedEvent as any, { eventId });
          }
        }
      });
    });
  });

  // Process rendered HTML to add lazy loading and prevent autoplay
  function processMediaElements(html: string): string {
    // Add loading="lazy" to all images
    html = html.replace(/<img([^>]*)>/gi, (match, attrs) => {
      // Don't add if already has loading attribute
      if (/loading\s*=/i.test(attrs)) {
        return match;
      }
      return `<img${attrs} loading="lazy">`;
    });

    // Ensure videos don't autoplay and use preload="none"
    html = html.replace(/<video([^>]*)>/gi, (match, attrs) => {
      let newAttrs = attrs;
      // Remove autoplay if present
      newAttrs = newAttrs.replace(/\s*autoplay\s*/gi, ' ');
      // Set preload to none if not already set
      if (!/preload\s*=/i.test(newAttrs)) {
        newAttrs += ' preload="none"';
      } else {
        newAttrs = newAttrs.replace(/preload\s*=\s*["']?[^"'\s>]+["']?/gi, 'preload="none"');
      }
      // Ensure autoplay is explicitly false
      if (!/autoplay\s*=/i.test(newAttrs)) {
        newAttrs += ' autoplay="false"';
      }
      return `<video${newAttrs}>`;
    });

    // Ensure audio doesn't autoplay and use preload="none"
    html = html.replace(/<audio([^>]*)>/gi, (match, attrs) => {
      let newAttrs = attrs;
      // Remove autoplay if present
      newAttrs = newAttrs.replace(/\s*autoplay\s*/gi, ' ');
      // Set preload to none if not already set
      if (!/preload\s*=/i.test(newAttrs)) {
        newAttrs += ' preload="none"';
      } else {
        newAttrs = newAttrs.replace(/preload\s*=\s*["']?[^"'\s>]+["']?/gi, 'preload="none"');
      }
      // Ensure autoplay is explicitly false
      if (!/autoplay\s*=/i.test(newAttrs)) {
        newAttrs += ' autoplay="false"';
      }
      return `<audio${newAttrs}>`;
    });

    return html;
  }

  $effect(() => {
    if (content) {
      // Process NIP-21 links before markdown parsing
      let processed = content;
      const links = findNIP21Links(content);
      
      // Replace links with placeholders, then restore after markdown parsing
      const placeholders: Map<string, { uri: string; parsed: any }> = new Map();
      let offset = 0;
      
      // Process in reverse order to maintain indices
      const sortedLinks = [...links].sort((a, b) => b.start - a.start);
      
      for (const link of sortedLinks) {
        // Use a special marker that will be replaced after markdown parsing
        // Use a format that markdown won't process: a code-like structure
        const placeholder = `\`NIP21PLACEHOLDER${offset}\``;
        const before = processed.slice(0, link.start);
        const after = processed.slice(link.end);
        processed = before + placeholder + after;
        placeholders.set(placeholder, { uri: link.uri, parsed: link.parsed });
        offset++;
      }

      const parseResult = marked.parse(processed);
      if (parseResult instanceof Promise) {
        parseResult.then((html) => {
          let finalHtml = sanitizeMarkdown(html);
          
          // Process media elements for lazy loading
          finalHtml = processMediaElements(finalHtml);
          
          // Replace placeholders with actual NIP-21 links/components
          for (const [placeholder, { uri, parsed }] of placeholders.entries()) {
            let replacement = '';
            
            try {
              // Handle hexID type (no decoding needed)
              if (parsed.type === 'hexID') {
                const eventId = parsed.data;
                const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                embeddedEvents.set(eventPlaceholder, eventId);
                replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
              } else {
              const decoded: any = nip19.decode(parsed.data);
                if (decoded.type === 'npub' || decoded.type === 'nprofile') {
                  const pubkey = decoded.type === 'npub' 
                    ? String(decoded.data)
                    : (decoded.data && typeof decoded.data === 'object' && 'pubkey' in decoded.data
                        ? String(decoded.data.pubkey)
                        : null);
                  if (pubkey) {
                    // Use custom element that will be replaced with ProfileBadge component
                    const badgePlaceholder = `PROFILE_BADGE_${pubkey.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                    profileBadges.set(badgePlaceholder, pubkey);
                    replacement = `<span class="nostr-profile-badge-placeholder inline-block" data-pubkey="${pubkey}" data-placeholder="${badgePlaceholder}"></span>`;
                  } else {
                    replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
                  }
              } else if (decoded.type === 'note') {
                const eventId = String(decoded.data);
                  // Use custom element for embedded event
                  const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, eventId);
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
              } else if (decoded.type === 'nevent' && decoded.data && typeof decoded.data === 'object' && 'id' in decoded.data) {
                const eventId = String(decoded.data.id);
                  const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, eventId);
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
                } else if (decoded.type === 'naddr' && decoded.data && typeof decoded.data === 'object') {
                  // For naddr, we'd need to fetch by kind+pubkey+d, but for now use the bech32 string
                  const eventPlaceholder = `EMBEDDED_EVENT_NADDR_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, parsed.data); // Store the bech32 string
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${parsed.data}" data-placeholder="${eventPlaceholder}"></span>`;
              } else {
                replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
                }
              }
            } catch {
              // Fallback to generic link if decoding fails
              const parsedType = parsed.type;
              if (parsedType === 'npub' || parsedType === 'nprofile') {
                // Try to extract pubkey from bech32
                try {
                  const decoded: any = nip19.decode(parsed.data);
                  const pubkey = decoded.type === 'npub' 
                    ? String(decoded.data)
                    : (decoded.data && typeof decoded.data === 'object' && 'pubkey' in decoded.data
                        ? String(decoded.data.pubkey)
                        : null);
                  if (pubkey) {
                    const badgePlaceholder = `PROFILE_BADGE_${pubkey.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                    profileBadges.set(badgePlaceholder, pubkey);
                    replacement = `<span class="nostr-profile-badge-placeholder inline-block" data-pubkey="${pubkey}" data-placeholder="${badgePlaceholder}"></span>`;
                  } else {
                    replacement = `<span class="nostr-link nostr-${parsedType}">${uri}</span>`;
                  }
                } catch {
                  replacement = `<span class="nostr-link nostr-${parsedType}">${uri}</span>`;
                }
              } else {
                replacement = `<span class="nostr-link nostr-${parsedType}">${uri}</span>`;
              }
            }
            
            // Replace placeholder - it will be in a <code> tag after markdown parsing
            // The placeholder is like `NIP21PLACEHOLDER0`, which becomes <code>NIP21PLACEHOLDER0</code>
            const placeholderText = placeholder.replace(/`/g, ''); // Remove backticks
            const codePlaceholder = `<code>${placeholderText}</code>`;
            // Escape special regex characters
            const escapedCodePlaceholder = codePlaceholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
            finalHtml = finalHtml.replace(new RegExp(escapedCodePlaceholder, 'g'), replacement);
            // Also try without code tag (in case markdown didn't process it)
            const escapedPlaceholder = placeholderText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
            finalHtml = finalHtml.replace(new RegExp(escapedPlaceholder, 'g'), replacement);
          }
          
          // Clean up any remaining placeholders (fallback) - look for code tags with our placeholder
          finalHtml = finalHtml.replace(/<code>NIP21PLACEHOLDER\d+<\/code>/g, '');
          finalHtml = finalHtml.replace(/NIP21PLACEHOLDER\d+/g, '');
          
          rendered = finalHtml;
        });
      } else {
        let finalHtml = sanitizeMarkdown(parseResult);
        
        // Process media elements for lazy loading
        finalHtml = processMediaElements(finalHtml);
        
        // Replace placeholders with actual NIP-21 links/components
        for (const [placeholder, { uri, parsed }] of placeholders.entries()) {
          let replacement = '';
          
          try {
              // Handle hexID type (no decoding needed)
              if (parsed.type === 'hexID') {
                const eventId = parsed.data;
                const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                embeddedEvents.set(eventPlaceholder, eventId);
                replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
              } else {
            const decoded: any = nip19.decode(parsed.data);
                if (decoded.type === 'npub' || decoded.type === 'nprofile') {
                  const pubkey = decoded.type === 'npub' 
                    ? String(decoded.data)
                    : (decoded.data && typeof decoded.data === 'object' && 'pubkey' in decoded.data
                        ? String(decoded.data.pubkey)
                        : null);
                  if (pubkey) {
                    const badgePlaceholder = `PROFILE_BADGE_${pubkey.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                    profileBadges.set(badgePlaceholder, pubkey);
                    replacement = `<span class="nostr-profile-badge-placeholder inline-block" data-pubkey="${pubkey}" data-placeholder="${badgePlaceholder}"></span>`;
                  } else {
                    replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
                  }
            } else if (decoded.type === 'note') {
              const eventId = String(decoded.data);
                  const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, eventId);
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
            } else if (decoded.type === 'nevent' && decoded.data && typeof decoded.data === 'object' && 'id' in decoded.data) {
              const eventId = String(decoded.data.id);
                  const eventPlaceholder = `EMBEDDED_EVENT_${eventId.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, eventId);
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${eventId}" data-placeholder="${eventPlaceholder}"></span>`;
                } else if (decoded.type === 'naddr' && decoded.data && typeof decoded.data === 'object') {
                  const eventPlaceholder = `EMBEDDED_EVENT_NADDR_${Date.now()}_${Math.random()}`;
                  embeddedEvents.set(eventPlaceholder, parsed.data);
                  replacement = `<span class="nostr-embedded-event-placeholder inline-block" data-event-id="${parsed.data}" data-placeholder="${eventPlaceholder}"></span>`;
            } else {
              replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
                }
            }
          } catch {
            // Fallback to generic link if decoding fails
            if (parsed.type === 'npub' || parsed.type === 'nprofile') {
              try {
                const decoded: any = nip19.decode(parsed.data);
                const pubkey = decoded.type === 'npub' 
                  ? String(decoded.data)
                  : (decoded.data && typeof decoded.data === 'object' && 'pubkey' in decoded.data
                      ? String(decoded.data.pubkey)
                      : null);
                if (pubkey) {
                  const badgePlaceholder = `PROFILE_BADGE_${pubkey.slice(0, 8)}_${Date.now()}_${Math.random()}`;
                  profileBadges.set(badgePlaceholder, pubkey);
                  replacement = `<div class="nostr-profile-badge-placeholder" data-pubkey="${pubkey}" data-placeholder="${badgePlaceholder}"></div>`;
                } else {
                  replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
                }
              } catch {
                replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
              }
            } else {
              replacement = `<span class="nostr-link nostr-${parsed.type}">${uri}</span>`;
            }
          }
          
          // Replace placeholder - it will be in a <code> tag after markdown parsing
          const placeholderText = placeholder.replace(/`/g, ''); // Remove backticks
          const codePlaceholder = `<code>${placeholderText}</code>`;
          // Escape special regex characters
          const escapedCodePlaceholder = codePlaceholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
          finalHtml = finalHtml.replace(new RegExp(escapedCodePlaceholder, 'g'), replacement);
          // Also try without code tag (in case markdown didn't process it)
          const escapedPlaceholder = placeholderText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
          finalHtml = finalHtml.replace(new RegExp(escapedPlaceholder, 'g'), replacement);
        }
        
        // Clean up any remaining placeholders (fallback)
        finalHtml = finalHtml.replace(/\u200B\u200B\u200BNIP21_LINK_\d+\u200B\u200B\u200B/g, '');
        
        rendered = finalHtml;
      }
    } else {
      rendered = '';
    }
  });
</script>

<div class="markdown-content anon-content" bind:this={containerElement}>
  {@html rendered}
</div>

<style>
  .markdown-content {
    line-height: var(--line-height);
  }

  .markdown-content :global(p) {
    margin: 0.5em 0;
  }

  .markdown-content :global(a) {
    color: #64748b;
    text-decoration: underline;
  }

  :global(.dark) .markdown-content :global(a) {
    color: #94a3b8;
  }

  .markdown-content :global(a:hover) {
    color: #475569;
  }

  :global(.dark) .markdown-content :global(a:hover) {
    color: #cbd5e1;
  }

  .markdown-content :global(.nostr-link) {
    color: var(--fog-accent, #64748b);
    text-decoration: underline;
    cursor: pointer;
  }

  :global(.dark) .markdown-content :global(.nostr-link) {
    color: var(--fog-dark-accent, #64748b);
  }

  .markdown-content :global(.nostr-link:hover) {
    color: var(--fog-text, #475569);
  }

  :global(.dark) .markdown-content :global(.nostr-link:hover) {
    color: var(--fog-dark-text, #cbd5e1);
  }

  .markdown-content :global(code) {
    background: #e2e8f0;
    padding: 0.2em 0.4em;
    border-radius: 3px;
    font-family: monospace;
    color: #475569;
  }

  :global(.dark) .markdown-content :global(code) {
    background: #475569;
    color: #cbd5e1;
  }

  .markdown-content :global(pre) {
    background: #e2e8f0;
    padding: 1em;
    border-radius: 5px;
    overflow-x: auto;
    border: 1px solid #cbd5e1;
  }

  :global(.dark) .markdown-content :global(pre) {
    background: #475569;
    border-color: #64748b;
  }

  .markdown-content :global(img) {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0.5em 0;
    filter: grayscale(100%) sepia(15%) hue-rotate(200deg) saturate(60%) brightness(0.95);
  }

  :global(.dark) .markdown-content :global(img) {
    filter: grayscale(100%) sepia(20%) hue-rotate(200deg) saturate(70%) brightness(0.9);
  }

  .markdown-content :global(.nostr-profile-badge-placeholder),
  .markdown-content :global(.nostr-embedded-event-placeholder) {
    display: inline-block;
    vertical-align: middle;
  }

  /* Style emojis in content */
  .markdown-content :global(span[role="img"]),
  .markdown-content :global(.emoji) {
    filter: grayscale(100%) sepia(15%) hue-rotate(200deg) saturate(60%) brightness(0.95);
    display: inline-block;
  }

  :global(.dark) .markdown-content :global(span[role="img"]),
  :global(.dark) .markdown-content :global(.emoji) {
    filter: grayscale(100%) sepia(20%) hue-rotate(200deg) saturate(70%) brightness(0.9);
  }
</style>
