/**
 * Markdown Detection and Conversion Utilities
 * 
 * Handles detection of markdown vs HTML content and conversion between formats
 */

/**
 * Detect if content is markdown or HTML
 * 
 * @param content - The content to check
 * @returns 'markdown' | 'html'
 */
export function detectContentType(content: string): 'markdown' | 'html' {
  if (!content || content.trim() === '') {
    return 'html';
  }

  // Check for markdown-specific patterns
  const markdownPatterns = [
    /^\*\*[^*]+\*\*/m,           // **bold**
    /^__[^_]+__/m,                // __bold__
    /^\*[^*]+\*/m,                // *italic*
    /^_[^_]+_/m,                  // _italic_
    /^#{1,6}\s/m,                 // # headings
    /^\[card[^\]]*\]/m,           // [card] syntax
    /^\[button\s+url=/m,          // [button url=...] syntax
    /^---$/m,                     // horizontal rules
    /^[\*\-•✓]\s/m,              // bullet points
  ];

  // Check for HTML-specific patterns
  const htmlPatterns = [
    /<[a-z][\s\S]*>/i,           // HTML tags
    /<\/[a-z]+>/i,                // Closing tags
    /&[a-z]+;/i,                  // HTML entities
  ];

  // Count markdown vs HTML indicators
  let markdownScore = 0;
  let htmlScore = 0;

  for (const pattern of markdownPatterns) {
    if (pattern.test(content)) {
      markdownScore++;
    }
  }

  for (const pattern of htmlPatterns) {
    if (pattern.test(content)) {
      htmlScore++;
    }
  }

  // If content has [card] or [button] syntax, it's definitely our markdown format
  if (/\[card[^\]]*\]/.test(content) || /\[button\s+url=/.test(content)) {
    return 'markdown';
  }

  // If content has HTML tags but no markdown, it's HTML
  if (htmlScore > 0 && markdownScore === 0) {
    return 'html';
  }

  // If content has markdown indicators, it's markdown
  if (markdownScore > 0) {
    return 'markdown';
  }

  // Default to HTML for safety
  return 'html';
}

/**
 * Convert markdown to HTML for display
 * 
 * @param markdown - Markdown content
 * @returns HTML content
 */
export function markdownToHtml(markdown: string): string {
  if (!markdown) return '';

  let html = markdown;

  // Parse [card:type] blocks (new syntax)
  html = html.replace(/\[card:(\w+)\]([\s\S]*?)\[\/card\]/g, (match, type, content) => {
    const cardClass = `card card-${type}`;
    const parsedContent = parseMarkdownBasics(content.trim());
    return `<div class="${cardClass}">${parsedContent}</div>`;
  });

  // Parse [card type="..."] blocks (old syntax - backward compatibility)
  html = html.replace(/\[card(?:\s+type="([^"]+)")?\]([\s\S]*?)\[\/card\]/g, (match, type, content) => {
    const cardClass = type ? `card card-${type}` : 'card';
    const parsedContent = parseMarkdownBasics(content.trim());
    return `<div class="${cardClass}">${parsedContent}</div>`;
  });

  // Parse [button:style](url)Text[/button] (new syntax)
  // Buttons are inline in TipTap, so don't wrap in <p>
  html = html.replace(/\[button:(\w+)\]\(([^)]+)\)([^\[]+)\[\/button\]/g, (match, style, url, text) => {
    if (style === 'link') {
      return `<a href="${url}" class="text-link">${text.trim()}</a>`;
    }
    const buttonClass = style === 'outline' ? 'button-outline' : 'button';
    return `<a href="${url}" class="${buttonClass}">${text.trim()}</a>`;
  });

  // Parse [button url="..."] shortcodes (old syntax - backward compatibility)
  html = html.replace(/\[button\s+url="([^"]+)"(?:\s+style="([^"]+)")?\]([^\[]+)\[\/button\]/g, (match, url, style, text) => {
    if (style === 'link') {
      return `<a href="${url}" class="text-link">${text.trim()}</a>`;
    }
    const buttonClass = style === 'outline' ? 'button-outline' : 'button';
    return `<a href="${url}" class="${buttonClass}">${text.trim()}</a>`;
  });

  // Parse remaining markdown
  html = parseMarkdownBasics(html);

  return html;
}

/**
 * Parse basic markdown syntax to HTML (exported for use in components)
 * 
 * @param text - Markdown text
 * @returns HTML text
 */
export function parseMarkdownBasics(text: string): string {
  let html = text;

  // Protect variables from markdown parsing by temporarily replacing them
  const variables: { [key: string]: string } = {};
  let varIndex = 0;
  html = html.replace(/\{([^}]+)\}/g, (match, varName) => {
    const placeholder = `<!--VAR${varIndex}-->`;
    variables[placeholder] = match;
    varIndex++;
    return placeholder;
  });

  // Headings
  html = html.replace(/^#### (.*$)/gim, '<h4>$1</h4>');
  html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
  html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
  html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');

  // Bold (don't match across newlines)
  html = html.replace(/\*\*([^\n*]+?)\*\*/g, '<strong>$1</strong>');
  html = html.replace(/__([^\n_]+?)__/g, '<strong>$1</strong>');

  // Italic (don't match across newlines)
  html = html.replace(/\*([^\n*]+?)\*/g, '<em>$1</em>');
  html = html.replace(/_([^\n_]+?)_/g, '<em>$1</em>');

  // Horizontal rules
  html = html.replace(/^---$/gm, '<hr>');

  // Parse [button:style](url)Text[/button] (new syntax) - must come before images
  // Allow whitespace and newlines between parts
  // Include data-button attributes for TipTap recognition
  html = html.replace(/\[button:(\w+)\]\(([^)]+)\)([\s\S]*?)\[\/button\]/g, (match, style, url, text) => {
    const trimmedText = text.trim();
    if (style === 'link') {
      return `<a href="${url}" class="text-link" data-button="" data-text="${trimmedText}" data-href="${url}" data-style="link">${trimmedText}</a>`;
    }
    const buttonClass = style === 'outline' ? 'button-outline' : 'button';
    return `<a href="${url}" class="${buttonClass}" data-button="" data-text="${trimmedText}" data-href="${url}" data-style="${style}">${trimmedText}</a>`;
  });

  // Parse [button url="..."] shortcodes (old syntax - backward compatibility)
  // Include data-button attributes for TipTap recognition
  html = html.replace(/\[button\s+url="([^"]+)"(?:\s+style="([^"]+)")?\]([^\[]+)\[\/button\]/g, (match, url, style, text) => {
    const buttonStyle = style || 'solid';
    const buttonClass = buttonStyle === 'outline' ? 'button-outline' : 'button';
    const trimmedText = text.trim();
    return `<a href="${url}" class="${buttonClass}" data-button="" data-text="${trimmedText}" data-href="${url}" data-style="${buttonStyle}">${trimmedText}</a>`;
  });

  // Images (must come before links)
  html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" style="max-width: 100%; height: auto; display: block; margin: 16px 0;">');

  // Links (but not button syntax)
  html = html.replace(/\[(?!button)([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');

  // Process lines for paragraphs and lists
  const lines = html.split('\n');
  let inList = false;
  let paragraphContent = '';
  const processedLines: string[] = [];

  const closeParagraph = () => {
    if (paragraphContent) {
      processedLines.push(`<p>${paragraphContent}</p>`);
      paragraphContent = '';
    }
  };

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    const trimmed = line.trim();

    // Empty line - close paragraph or list
    if (!trimmed) {
      if (inList) {
        processedLines.push('</ul>');
        inList = false;
      }
      closeParagraph();
      processedLines.push('');
      continue;
    }

    // Check if line is a list item
    if (/^[\*\-•✓]\s/.test(trimmed)) {
      closeParagraph();
      const content = trimmed.replace(/^[\*\-•✓]\s/, '');
      if (!inList) {
        processedLines.push('<ul>');
        inList = true;
      }
      processedLines.push(`<li>${content}</li>`);
      continue;
    }

    // Close list if we're in one
    if (inList) {
      processedLines.push('</ul>');
      inList = false;
    }

    // Block-level HTML tags - don't wrap in paragraph
    // But inline tags like <strong>, <em>, <a> should be part of paragraph
    const blockTags = /^<(div|h1|h2|h3|h4|h5|h6|p|ul|ol|li|hr|table|blockquote)/i;
    if (blockTags.test(trimmed)) {
      closeParagraph();
      processedLines.push(line);
      continue;
    }

    // Regular text line - accumulate in paragraph
    if (paragraphContent) {
      // Add line break before continuation
      paragraphContent += '<br>' + trimmed;
    } else {
      // Start new paragraph
      paragraphContent = trimmed;
    }
  }

  // Close any open tags
  if (inList) {
    processedLines.push('</ul>');
  }
  closeParagraph();

  html = processedLines.join('\n');

  // Restore variables
  Object.entries(variables).forEach(([placeholder, original]) => {
    html = html.replace(new RegExp(placeholder, 'g'), original);
  });

  return html;
}

/**
 * Convert HTML back to markdown (for editing)
 * 
 * @param html - HTML content
 * @returns Markdown content
 */
export function htmlToMarkdown(html: string): string {
  if (!html) return '';

  let markdown = html;

  // Convert <div class="card"> back to [card]
  markdown = markdown.replace(/<div class="card(?:\s+card-([^"]+))?">([\s\S]*?)<\/div>/g, (match, type, content) => {
    const mdContent = parseHtmlToMarkdownBasics(content.trim());
    return type ? `[card type="${type}"]\n${mdContent}\n[/card]` : `[card]\n${mdContent}\n[/card]`;
  });

  // Convert buttons back to [button] syntax
  // TipTap button format with data attributes: <a data-button data-href="..." data-style="..." data-text="...">text</a>
  markdown = markdown.replace(/<a[^>]*data-button[^>]*data-href="([^"]+)"[^>]*data-style="([^"]*)"[^>]*>([^<]+)<\/a>/gi, (match, url, style, text) => {
    const styleAttr = style === 'outline' ? ' style="outline"' : ' style="solid"';
    return `[button url="${url}"${styleAttr}]${text.trim()}[/button]`;
  });

  // Alternate order: data-style before data-href
  markdown = markdown.replace(/<a[^>]*data-button[^>]*data-style="([^"]*)"[^>]*data-href="([^"]+)"[^>]*>([^<]+)<\/a>/gi, (match, style, url, text) => {
    const styleAttr = style === 'outline' ? ' style="outline"' : ' style="solid"';
    return `[button url="${url}"${styleAttr}]${text.trim()}[/button]`;
  });

  // Simple data-button fallback (just has href and class)
  markdown = markdown.replace(/<a[^>]*href="([^"]+)"[^>]*class="(button[^"]*)"[^>]*data-button[^>]*>([^<]+)<\/a>/gi, (match, url, className, text) => {
    const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
    return `[button url="${url}"${style}]${text.trim()}[/button]`;
  });

  // Buttons wrapped in p tags (from preview HTML): <p><a href="..." class="button...">text</a></p>
  markdown = markdown.replace(/<p[^>]*><a href="([^"]+)" class="(button[^"]*)"[^>]*>([^<]+)<\/a><\/p>/g, (match, url, className, text) => {
    const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
    return `[button url="${url}"${style}]${text.trim()}[/button]`;
  });

  // Direct button links without p wrapper
  markdown = markdown.replace(/<a href="([^"]+)" class="(button[^"]*)"[^>]*>([^<]+)<\/a>/g, (match, url, className, text) => {
    const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
    return `[button url="${url}"${style}]${text.trim()}[/button]`;
  });

  // Convert remaining HTML to markdown
  markdown = parseHtmlToMarkdownBasics(markdown);

  return markdown;
}

/**
 * Parse HTML back to basic markdown
 * 
 * @param html - HTML text
 * @returns Markdown text
 */
function parseHtmlToMarkdownBasics(html: string): string {
  let markdown = html;

  // Headings
  markdown = markdown.replace(/<h1>(.*?)<\/h1>/gi, '# $1');
  markdown = markdown.replace(/<h2>(.*?)<\/h2>/gi, '## $1');
  markdown = markdown.replace(/<h3>(.*?)<\/h3>/gi, '### $1');
  markdown = markdown.replace(/<h4>(.*?)<\/h4>/gi, '#### $1');

  // Bold
  markdown = markdown.replace(/<strong>(.*?)<\/strong>/gi, '**$1**');
  markdown = markdown.replace(/<b>(.*?)<\/b>/gi, '**$1**');

  // Italic
  markdown = markdown.replace(/<em>(.*?)<\/em>/gi, '*$1*');
  markdown = markdown.replace(/<i>(.*?)<\/i>/gi, '*$1*');

  // Links
  markdown = markdown.replace(/<a href="([^"]+)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)');

  // Horizontal rules
  markdown = markdown.replace(/<hr\s*\/?>/gi, '\n---\n');

  // Lists
  markdown = markdown.replace(/<ul>([\s\S]*?)<\/ul>/gi, (match, content) => {
    return content.replace(/<li>(.*?)<\/li>/gi, '- $1\n');
  });

  // Paragraphs
  markdown = markdown.replace(/<p>(.*?)<\/p>/gi, '$1\n\n');

  // Clean up extra newlines
  markdown = markdown.replace(/\n{3,}/g, '\n\n');

  return markdown.trim();
}
