// ==========================================
// ChatPane Kit — CodeBlock Component
// ==========================================
// Enhanced code block: language badge, copy button.
// Independently importable.
//
// Usage (from markdown post-processing):
//   Enhances <pre><code> blocks after markdown rendering.

const html = window.html;
const { useState, useCallback } = window.hooks;

/**
 * SVG icons for copy/check.
 */
const COPY_SVG = html`
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <rect x="9" y="9" width="13" height="13" rx="2"/>
        <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
    </svg>`;

const CHECK_SVG = html`
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <polyline points="20 6 9 17 4 12"/>
    </svg>`;

/**
 * CodeBlock — wraps a <pre><code> block with language badge + copy button.
 *
 * @param {{ code: string, language?: string }} props
 */
export function CodeBlock({ code, language }) {
    const [copied, setCopied] = useState(false);

    const _copy = useCallback(async () => {
        try {
            await navigator.clipboard.writeText(code);
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
        } catch (_) {
            // Fallback
            const ta = document.createElement('textarea');
            ta.value = code;
            ta.style.cssText = 'position:fixed;left:-9999px';
            document.body.appendChild(ta);
            ta.select();
            document.execCommand('copy');
            document.body.removeChild(ta);
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
        }
    }, [code]);

    const langLabel = language && language !== 'text' ? language : null;

    return html`
        <div class="sw-code-block">
            <div class="sw-code-block__header">
                ${langLabel && html`<span class="sw-code-block__lang">${langLabel}</span>`}
                <button class="sw-code-block__copy"
                        title=${copied ? 'Copied!' : 'Copy code'}
                        onClick=${_copy}
                        aria-label="Copy code to clipboard">
                    ${copied ? CHECK_SVG : COPY_SVG}
                    <span class="sw-code-block__copy-text">${copied ? 'Copied' : 'Copy'}</span>
                </button>
            </div>
            <pre class="sw-code-block__pre"><code class=${langLabel ? 'language-' + langLabel : ''}
                 dangerouslySetInnerHTML=${{ __html: _escapeHtml(code) }} /></pre>
        </div>`;
}

const _escMap = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' };
function _escapeHtml(text) {
    return text.replace(/[&<>"']/g, c => _escMap[c]);
}

/**
 * Post-process rendered markdown HTML to enhance code blocks.
 * Extracts language from class="language-xxx" and returns
 * an array of { type, code, language } blocks for Preact rendering.
 *
 * @param {string} html — rendered markdown HTML
 * @returns {{ segments: Array<{type: 'html'|'code', html?: string, code?: string, language?: string}> }}
 */
export function extractCodeBlocks(htmlStr) {
    // Match <pre><code class="language-xxx">...</code></pre> blocks
    const pattern = /<pre><code(?:\s+class="language-(\w+)")?>([\s\S]*?)<\/code><\/pre>/g;
    const segments = [];
    let lastIndex = 0;
    let match;

    while ((match = pattern.exec(htmlStr)) !== null) {
        // Push preceding HTML
        if (match.index > lastIndex) {
            segments.push({ type: 'html', html: htmlStr.slice(lastIndex, match.index) });
        }
        // Push code block
        const language = match[1] || '';
        const code = _unescapeHtml(match[2]);
        segments.push({ type: 'code', code, language });
        lastIndex = match.index + match[0].length;
    }

    // Push trailing HTML
    if (lastIndex < htmlStr.length) {
        segments.push({ type: 'html', html: htmlStr.slice(lastIndex) });
    }

    return segments;
}

function _unescapeHtml(text) {
    return text
        .replace(/&amp;/g, '&')
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'");
}
