import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import React__default, { useState, useMemo, useCallback } from 'react';
import { Prism } from 'react-syntax-highlighter';
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { DocumentTextIcon, DocumentCheckIcon, DocumentDuplicateIcon } from '@heroicons/react/24/outline';
import { codeBlockTheme } from './CodeBlock.theme.js';
import { LanguageIcon } from './LanguageIcon.js';
import { cn } from '../../../utils/cn.js';

/**
 * CodeBlock - Syntax highlighted code display with copy-to-clipboard
 *
 * Features:
 * - Syntax highlighting for 20+ languages
 * - Copy-to-clipboard with visual feedback
 * - Optional line numbers
 * - Line highlighting
 * - Diff view (additions/deletions)
 * - Light/dark theme support
 * - Full className override support (shadcn pattern)
 *
 * @example
 * ```tsx
 * <CodeBlock language="python" showLineNumbers copyable>
 *   {`def hello_world():
 *     print("Hello from AI!")`}
 * </CodeBlock>
 * ```
 *
 * @example
 * ```tsx
 * <CodeBlock
 *   language="typescript"
 *   highlightLines={[2, 3]}
 *   filename="example.ts"
 * >
 *   {code}
 * </CodeBlock>
 * ```
 */
const CodeBlock = React__default.forwardRef(({ children, language = "text", showLineNumbers = false, highlightLines = [], diffMode = false, copyable = true, filename, showLanguage = true, syntaxTheme = "light", wrapLines = false, maxHeight, className, theme: customTheme = {}, ...props }, ref) => {
    const [copied, setCopied] = useState(false);
    // Merge theme
    const mergedTheme = useMemo(() => ({
        baseStyle: customTheme.baseStyle || codeBlockTheme.baseStyle,
        header: customTheme.header || codeBlockTheme.header,
        headerLeft: customTheme.headerLeft || codeBlockTheme.headerLeft,
        headerRight: customTheme.headerRight || codeBlockTheme.headerRight,
        filename: customTheme.filename || codeBlockTheme.filename,
        languageLabel: customTheme.languageLabel || codeBlockTheme.languageLabel,
        codeWrapper: customTheme.codeWrapper || codeBlockTheme.codeWrapper,
        lineNumber: customTheme.lineNumber || codeBlockTheme.lineNumber,
        highlightedLine: customTheme.highlightedLine || codeBlockTheme.highlightedLine,
        diffAddition: customTheme.diffAddition || codeBlockTheme.diffAddition,
        diffDeletion: customTheme.diffDeletion || codeBlockTheme.diffDeletion,
        copyButton: customTheme.copyButton || codeBlockTheme.copyButton,
        copySuccess: customTheme.copySuccess || codeBlockTheme.copySuccess,
    }), [customTheme]);
    // Normalize code content
    const code = useMemo(() => {
        return typeof children === "string"
            ? children.replace(/\n$/, "")
            : String(children);
    }, [children]);
    // Handle copy to clipboard
    const handleCopy = useCallback(async () => {
        try {
            await navigator.clipboard.writeText(code);
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
        }
        catch (err) {
            if (process.env.NODE_ENV !== "production") {
                console.error("[CodeBlock]: Failed to copy to clipboard", err);
            }
        }
    }, [code]);
    // Determine if line should be highlighted
    const isLineHighlighted = useCallback((lineNumber) => {
        return highlightLines.includes(lineNumber);
    }, [highlightLines]);
    // Determine diff styling for a line
    const getDiffStyle = useCallback((lineContent, lineNumber) => {
        if (!diffMode)
            return null;
        if (diffMode === "additions") {
            return mergedTheme.diffAddition;
        }
        if (diffMode === "deletions") {
            return mergedTheme.diffDeletion;
        }
        if (diffMode === "diff") {
            const trimmed = lineContent.trimStart();
            if (trimmed.startsWith("+")) {
                return mergedTheme.diffAddition;
            }
            if (trimmed.startsWith("-")) {
                return mergedTheme.diffDeletion;
            }
        }
        return null;
    }, [diffMode, mergedTheme]);
    // Get display language name
    const displayLanguage = useMemo(() => {
        const languageMap = {
            javascript: "JavaScript",
            typescript: "TypeScript",
            jsx: "JSX",
            tsx: "TSX",
            python: "Python",
            java: "Java",
            c: "C",
            cpp: "C++",
            csharp: "C#",
            go: "Go",
            rust: "Rust",
            ruby: "Ruby",
            php: "PHP",
            sql: "SQL",
            html: "HTML",
            css: "CSS",
            scss: "SCSS",
            json: "JSON",
            yaml: "YAML",
            markdown: "Markdown",
            bash: "Bash",
            shell: "Shell",
            powershell: "PowerShell",
            swift: "Swift",
            kotlin: "Kotlin",
            scala: "Scala",
            graphql: "GraphQL",
            dockerfile: "Dockerfile",
            xml: "XML",
            text: "Plain Text",
        };
        return languageMap[language.toLowerCase()] || language.toUpperCase();
    }, [language]);
    // Check if header should be shown
    const showHeader = filename || showLanguage;
    // Pre-split code lines for lineProps
    const codeLines = useMemo(() => code.split("\n"), [code]);
    // Custom line props for highlighting
    const lineProps = useCallback((lineNumber) => {
        const lineContent = codeLines[lineNumber - 1] || "";
        const diffStyle = getDiffStyle(lineContent, lineNumber);
        const highlighted = isLineHighlighted(lineNumber);
        const baseStyle = {
            display: "block",
        };
        let lineClassName = "";
        if (diffStyle) {
            lineClassName = diffStyle;
        }
        else if (highlighted) {
            lineClassName = mergedTheme.highlightedLine;
        }
        return {
            style: baseStyle,
            className: lineClassName,
        };
    }, [codeLines, getDiffStyle, isLineHighlighted, mergedTheme]);
    return (jsxs("div", { ref: ref, className: cn(mergedTheme.baseStyle, className), ...props, children: [showHeader && (jsxs("div", { className: mergedTheme.header, children: [jsx("div", { className: mergedTheme.headerLeft, children: filename && (jsxs(Fragment, { children: [jsx(DocumentTextIcon, { className: "size-4 text-[var(--color-text-muted)]" }), jsx("span", { className: mergedTheme.filename, children: filename })] })) }), jsxs("div", { className: mergedTheme.headerRight, children: [showLanguage && (jsxs("div", { className: "flex items-center gap-2", children: [jsx(LanguageIcon, { language: language, className: "size-4" }), jsx("span", { className: mergedTheme.languageLabel, children: displayLanguage })] })), copyable && (jsx("button", { onClick: handleCopy, className: cn(mergedTheme.copyButton, copied && mergedTheme.copySuccess), "aria-label": copied ? "Copied!" : "Copy code", title: copied ? "Copied!" : "Copy code", children: copied ? (jsx(DocumentCheckIcon, { className: "size-4" })) : (jsx(DocumentDuplicateIcon, { className: "size-4" })) }))] })] })), jsx("div", { className: mergedTheme.codeWrapper, style: {
                    maxHeight: maxHeight,
                    overflowY: maxHeight ? "auto" : undefined,
                }, children: jsx(Prism, { language: language, style: syntaxTheme === "dark" ? oneDark : oneLight, showLineNumbers: showLineNumbers, wrapLines: true, wrapLongLines: wrapLines, lineProps: lineProps, lineNumberStyle: {
                        minWidth: "2.5em",
                        paddingRight: "1em",
                        textAlign: "right",
                        userSelect: "none",
                        opacity: 0.5,
                    }, customStyle: {
                        margin: 0,
                        padding: "1rem",
                        fontSize: "0.875rem",
                        lineHeight: "1.5",
                        background: "transparent",
                    }, children: code }) }), !showHeader && copyable && (jsx("button", { onClick: handleCopy, className: cn("absolute top-2 right-2", mergedTheme.copyButton, copied && mergedTheme.copySuccess), "aria-label": copied ? "Copied!" : "Copy code", title: copied ? "Copied!" : "Copy code", children: copied ? (jsx(DocumentCheckIcon, { className: "size-4" })) : (jsx(DocumentDuplicateIcon, { className: "size-4" })) }))] }));
});
CodeBlock.displayName = "CodeBlock";

export { CodeBlock };
