'use client';

/**
 * Renders message content — markdown with @[type:id:label] mentions.
 * Mentions are protected from markdown parsing by replacing them with
 * placeholder tokens before rendering, then restored in custom text components.
 */

import { memo, useMemo } from 'react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { cn } from '@/lib/utils';

interface MessageContentProps {
  content: string;
  onMentionClick?: (type: string, id: string, label: string) => void;
}

const MENTION_RE = /@\[([a-z]+):([^:\]]+):([^\]]+)\]/g;

interface MentionInfo {
  type: string;
  id: string;
  label: string;
}

/** Replace @[type:id:label] with ◊MENTION_i◊ placeholders (◊ is unlikely in real content) */
function extractMentions(content: string): { safeContent: string; mentions: MentionInfo[] } {
  const mentions: MentionInfo[] = [];
  const safeContent = content.replace(MENTION_RE, (_match, type, id, label) => {
    const idx = mentions.length;
    mentions.push({ type, id, label });
    return `\u200BMENTION_${idx}\u200B`;  // zero-width spaces prevent markdown parsing
  });
  return { safeContent, mentions };
}

function getMentionStyle(type: string): string {
  switch (type) {
    case 'user':   return 'bg-blue-50 text-blue-600 dark:bg-blue-900/30 dark:text-blue-300';
    case 'channel': return 'bg-gray-50 text-gray-600 dark:bg-gray-800 dark:text-gray-300';
    case 'ai':     return 'bg-green-50 text-green-600 dark:bg-green-900/30 dark:text-green-300';
    case 'command': return 'bg-amber-50 text-amber-600 dark:bg-amber-900/30 dark:text-amber-300';
    default:        return 'bg-muted text-foreground';
  }
}

/** Restore mention placeholders inside a text node into React elements */
function restoreMentions(text: string, mentions: MentionInfo[], onMentionClick?: (type: string, id: string, label: string) => void): React.ReactNode[] {
  const MENTION_PLACEHOLDER_RE = /\u200BMENTION_(\d+)\u200B/g;
  const parts: React.ReactNode[] = [];
  let lastIndex = 0;
  let match: RegExpExecArray | null;

  while ((match = MENTION_PLACEHOLDER_RE.exec(text)) !== null) {
    if (match.index > lastIndex) {
      parts.push(text.slice(lastIndex, match.index));
    }
    const idx = parseInt(match[1], 10);
    const m = mentions[idx];
    if (m) {
      parts.push(
        <span
          key={`mention-${idx}`}
          role={onMentionClick ? 'button' : undefined}
          tabIndex={onMentionClick ? 0 : undefined}
          className={cn(
            'inline-flex items-center gap-0.5 rounded px-1 py-0.5 font-medium text-xs mx-0.5',
            getMentionStyle(m.type),
          )}
          onClick={() => onMentionClick?.(m.type, m.id, m.label)}
          onKeyDown={(e) => {
            if ((e.key === 'Enter' || e.key === ' ') && onMentionClick) {
              e.preventDefault();
              onMentionClick(m.type, m.id, m.label);
            }
          }}
        >
          @{m.label}
        </span>,
      );
    }
    lastIndex = MENTION_PLACEHOLDER_RE.lastIndex;
  }

  if (lastIndex < text.length) {
    parts.push(text.slice(lastIndex));
  }

  return parts;
}

export const MessageContent = memo(function MessageContent({ content, onMentionClick }: MessageContentProps) {
  const { safeContent, mentions } = useMemo(() => extractMentions(content), [content]);

  return (
    <div
      className={cn(
        'text-[15px] text-foreground',
        'max-w-full min-w-0 break-words',
        '[&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-xs',
        '[&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:overflow-x-auto',
        '[&_p]:whitespace-pre-wrap [&_p]:leading-[1.4] [&_p]:my-1',
        '[&_ul]:list-disc [&_ul]:pl-6 [&_ul]:my-1',
        '[&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:my-1',
        '[&_li]:my-0.5',
        '[&_blockquote]:border-l-2 [&_blockquote]:border-primary [&_blockquote]:pl-4 [&_blockquote]:my-1',
        '[&_h1]:text-xl [&_h1]:font-semibold [&_h1]:my-2',
        '[&_h2]:text-lg [&_h2]:font-semibold [&_h2]:my-2',
        '[&_h3]:text-base [&_h3]:font-semibold [&_h3]:my-1.5',
        '[&_strong]:font-semibold',
        '[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2',
        '[&_hr]:border-foreground/20 [&_hr]:my-2',
        '[&_table]:w-full [&_table]:border-collapse [&_table]:rounded-md [&_table]:border [&_table]:border-foreground/20 [&_table]:my-2',
        '[&_th]:border [&_th]:border-foreground/20 [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-bold',
        '[&_td]:border [&_td]:border-foreground/20 [&_td]:px-2 [&_td]:py-1 [&_td]:text-left',
        '[&_tr]:border-t [&_tr]:even:bg-muted',
      )}
    >
    <Markdown
      remarkPlugins={[remarkGfm]}
      components={{
        p: ({ children }) => {
          // Restore mentions in paragraph text nodes
          if (typeof children === 'string') {
            return <p>{restoreMentions(children, mentions, onMentionClick)}</p>;
          }
          // Children may be an array of strings/elements
          if (Array.isArray(children)) {
            const restored = children.map((child) => {
              if (typeof child === 'string') {
                return restoreMentions(child, mentions, onMentionClick);
              }
              return child;
            });
            return <p>{restored}</p>;
          }
          return <p>{children}</p>;
        },
        li: ({ children }) => {
          if (typeof children === 'string') {
            return <li>{restoreMentions(children, mentions, onMentionClick)}</li>;
          }
          if (Array.isArray(children)) {
            const restored = children.map((child) => {
              if (typeof child === 'string') {
                return restoreMentions(child, mentions, onMentionClick);
              }
              return child;
            });
            return <li>{restored}</li>;
          }
          return <li>{children}</li>;
        },
        strong: ({ children }) => {
          if (typeof children === 'string') {
            return <strong>{restoreMentions(children, mentions, onMentionClick)}</strong>;
          }
          return <strong>{children}</strong>;
        },
        em: ({ children }) => {
          if (typeof children === 'string') {
            return <em>{restoreMentions(children, mentions, onMentionClick)}</em>;
          }
          return <em>{children}</em>;
        },
        code: ({ className, children, ...props }) => {
          // Inline code — don't restore mentions inside code blocks
          const isBlock = typeof className === 'string' && className.includes('language-');
          if (isBlock) {
            // Fenced code block — let the pre wrapper handle it
            return <code className={className} {...props}>{children}</code>;
          }
          return (
            <code
              className="font-mono rounded bg-muted px-1 py-0.5 text-xs"
              {...props}
            >
              {children}
            </code>
          );
        },
        pre: ({ children }) => {
          // Preserve code blocks as-is, no mention restoration
          return <pre className="rounded-md bg-muted p-3 overflow-x-auto">{children}</pre>;
        },
      }}
    >
      {safeContent}
    </Markdown>
    </div>
  );
});