'use client';

import { useCallback, useMemo, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import { cn } from '@/lib/cn';
import type { Message } from '@/lib/types';

interface MessageBubbleProps {
  message: Message;
}

export function MessageBubble({ message }: MessageBubbleProps): React.ReactElement {
  const isUser = message.role === 'user';
  const isSystem = message.role === 'system';
  const [copied, setCopied] = useState(false);
  const [thinkingExpanded, setThinkingExpanded] = useState(false);
  const { response, thinking } = useMemo(
    () => parseThinking(message.content, message.thinking),
    [message.content, message.thinking],
  );

  const handleCopy = useCallback(async (): Promise<void> => {
    try {
      await navigator.clipboard.writeText(response);
      setCopied(true);
      window.setTimeout(() => setCopied(false), 1800);
    } catch (error) {
      console.error('[MessageBubble] Failed to copy message:', error);
    }
  }, [response]);

  if (isSystem) {
    return (
      <div className="flex justify-center">
        <div
          className="max-w-[42rem] rounded-full border px-3 py-1.5 text-xs backdrop-blur-sm"
          style={{
            borderColor: 'var(--color-border)',
            backgroundColor: 'color-mix(in srgb, var(--color-surface) 70%, transparent)',
            color: 'var(--color-muted)',
          }}
        >
          <span>{response}</span>
        </div>
      </div>
    );
  }

  return (
    <div className={cn('group flex', isUser ? 'justify-end' : 'justify-start')}>
      <div
        className={cn(
          'flex max-w-[min(78ch,85%)] flex-col gap-2',
          isUser ? 'items-end' : 'items-start',
        )}
      >
        <div className={cn('flex items-center gap-2 text-[11px]', isUser && 'flex-row-reverse')}>
          <span className="font-medium text-[var(--color-text-2)]">
            {isUser ? 'You' : 'Assistant'}
          </span>
          {!isUser && message.model ? (
            <span
              className="rounded-full border px-2 py-0.5 font-medium text-[var(--color-text-2)]"
              style={{
                backgroundColor: 'color-mix(in srgb, var(--color-surface-2) 82%, transparent)',
                borderColor: 'var(--color-border)',
              }}
              title={message.provider ? `Provider: ${message.provider}` : undefined}
            >
              {message.model}
            </span>
          ) : null}
          {!isUser && typeof message.totalTokens === 'number' && message.totalTokens > 0 ? (
            <span
              className="rounded-full border px-2 py-0.5 text-[var(--color-muted)]"
              style={{ borderColor: 'var(--color-border)' }}
            >
              {formatTokenCount(message.totalTokens)}
            </span>
          ) : null}
          <span className="text-[var(--color-muted)]">{formatTimestamp(message.createdAt)}</span>
        </div>

        {thinking && !isUser ? (
          <div
            className="w-full overflow-hidden rounded-2xl border"
            style={{
              backgroundColor: 'color-mix(in srgb, var(--color-surface-2) 88%, transparent)',
              borderColor: 'var(--color-border)',
            }}
          >
            <button
              type="button"
              onClick={() => setThinkingExpanded((prev) => !prev)}
              className="flex w-full items-center gap-2 px-3 py-2 text-left text-xs font-medium text-[var(--color-text-2)] transition-colors hover:bg-black/5"
              aria-expanded={thinkingExpanded}
            >
              <span
                className={cn(
                  'inline-block text-[10px] transition-transform',
                  thinkingExpanded && 'rotate-90',
                )}
              >
                ▶
              </span>
              <span>Chain of thought</span>
              <span className="ml-auto text-[var(--color-muted)]">
                {thinkingExpanded ? 'Hide' : 'Show'}
              </span>
            </button>
            {thinkingExpanded ? (
              <pre
                className="overflow-x-auto border-t px-3 py-3 font-mono text-xs leading-6 whitespace-pre-wrap"
                style={{
                  borderColor: 'var(--color-border)',
                  backgroundColor: 'var(--color-bg-deep)',
                  color: 'var(--color-text-2)',
                }}
              >
                {thinking}
              </pre>
            ) : null}
          </div>
        ) : null}

        <div
          className={cn(
            'relative w-full rounded-3xl px-4 py-3 text-sm shadow-[var(--shadow-ms-sm)]',
            !isUser && 'border',
          )}
          style={{
            backgroundColor: isUser ? 'var(--color-ms-blue-500)' : 'var(--color-surface)',
            color: isUser ? '#fff' : 'var(--color-text)',
            borderColor: isUser ? 'transparent' : 'var(--color-border)',
          }}
        >
          <div className="max-w-none">
            <ReactMarkdown
              components={{
                p: ({ children }) => <p className="mb-3 leading-7 last:mb-0">{children}</p>,
                ul: ({ children }) => <ul className="mb-3 list-disc pl-5 last:mb-0">{children}</ul>,
                ol: ({ children }) => (
                  <ol className="mb-3 list-decimal pl-5 last:mb-0">{children}</ol>
                ),
                li: ({ children }) => <li className="mb-1">{children}</li>,
                a: ({ href, children }) => (
                  <a
                    href={href}
                    className="font-medium underline underline-offset-4"
                    target="_blank"
                    rel="noreferrer"
                  >
                    {children}
                  </a>
                ),
                pre: ({ children }) => <div className="mb-3 last:mb-0">{children}</div>,
                code: ({ className, children, ...props }) => {
                  const language = className?.replace('language-', '');
                  const content = String(children).replace(/\n$/, '');
                  const isInline = !className;

                  if (isInline) {
                    return (
                      <code
                        className="rounded-md px-1.5 py-0.5 font-mono text-[0.9em]"
                        style={{
                          backgroundColor:
                            'color-mix(in srgb, var(--color-bg-deep) 76%, transparent)',
                        }}
                        {...props}
                      >
                        {children}
                      </code>
                    );
                  }

                  return (
                    <div
                      className="overflow-hidden rounded-2xl border"
                      style={{
                        backgroundColor: 'var(--color-bg-deep)',
                        borderColor: 'var(--color-border)',
                      }}
                    >
                      <div
                        className="border-b px-3 py-2 font-mono text-[11px] uppercase tracking-[0.18em] text-[var(--color-muted)]"
                        style={{ borderColor: 'var(--color-border)' }}
                      >
                        {language || 'code'}
                      </div>
                      <pre className="overflow-x-auto p-3">
                        <code
                          className={cn('font-mono text-[13px] leading-6', className)}
                          {...props}
                        >
                          {content}
                        </code>
                      </pre>
                    </div>
                  );
                },
                blockquote: ({ children }) => (
                  <blockquote
                    className="mb-3 border-l-2 pl-4 italic last:mb-0"
                    style={{ borderColor: 'var(--color-ms-blue-500)' }}
                  >
                    {children}
                  </blockquote>
                ),
              }}
            >
              {response}
            </ReactMarkdown>
          </div>

          <button
            type="button"
            onClick={() => void handleCopy()}
            className="absolute -right-2 -top-2 rounded-full border p-2 opacity-0 shadow-[var(--shadow-ms-md)] transition-all group-hover:opacity-100 focus:opacity-100"
            style={{
              backgroundColor: 'var(--color-surface)',
              borderColor: 'var(--color-border)',
              color: copied ? 'var(--color-success)' : 'var(--color-text-2)',
            }}
            aria-label={copied ? 'Copied' : 'Copy message'}
            title={copied ? 'Copied' : 'Copy message'}
          >
            {copied ? '✓' : '⧉'}
          </button>
        </div>
      </div>
    </div>
  );
}

function parseThinking(
  content: string,
  thinking?: string,
): { response: string; thinking: string | null } {
  if (thinking) {
    return { response: content, thinking };
  }

  const regex = /<(?:thinking|think)>([\s\S]*?)<\/(?:thinking|think)>/gi;
  const matches = [...content.matchAll(regex)];
  if (matches.length === 0) {
    return { response: content, thinking: null };
  }

  return {
    response: content.replace(regex, '').trim(),
    thinking:
      matches
        .map((match) => match[1]?.trim() ?? '')
        .filter(Boolean)
        .join('\n\n') || null,
  };
}

function formatTimestamp(createdAt: string): string {
  return new Date(createdAt).toLocaleTimeString([], {
    hour: '2-digit',
    minute: '2-digit',
  });
}

function formatTokenCount(totalTokens: number): string {
  if (totalTokens >= 1_000_000) return `${(totalTokens / 1_000_000).toFixed(1)}M tokens`;
  if (totalTokens >= 1_000) return `${(totalTokens / 1_000).toFixed(1)}k tokens`;
  return `${totalTokens} tokens`;
}
