import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, memo, useRef } from 'react';
import { X, ChevronLeft, ChevronRight } from 'lucide-react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { prism, vscDarkPlus, } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { useSessionFilesStore } from '../../stores/sessionFilesStore';
import { useSidebarStore } from '../../stores/sidebarStore';
import { Button } from '../ui/Button';
function transformToUnifiedDiff(patch) {
    const lines = patch.split('\n');
    const result = [];
    let addCount = 0;
    let removeCount = 0;
    const diffLines = [];
    for (const line of lines) {
        if (line.startsWith('*** Begin Patch') ||
            line.startsWith('*** End Patch') ||
            line.startsWith('*** Update File:') ||
            line.startsWith('*** Add File:') ||
            line.startsWith('*** Delete File:')) {
            if (diffLines.length > 0) {
                result.push(`@@ -1,${removeCount} +1,${addCount} @@`);
                result.push(...diffLines);
                diffLines.length = 0;
                addCount = 0;
                removeCount = 0;
            }
            result.push(line);
            continue;
        }
        if (line.match(/^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/)) {
            if (diffLines.length > 0) {
                result.push(`@@ -1,${removeCount} +1,${addCount} @@`);
                result.push(...diffLines);
                diffLines.length = 0;
                addCount = 0;
                removeCount = 0;
            }
            result.push(line);
            continue;
        }
        if (line.startsWith('@@')) {
            result.push(line);
            continue;
        }
        if (line.startsWith('+')) {
            addCount++;
            diffLines.push(line);
        }
        else if (line.startsWith('-')) {
            removeCount++;
            diffLines.push(line);
        }
        else if (line.startsWith(' ') || line.startsWith('\t')) {
            addCount++;
            removeCount++;
            diffLines.push(line.startsWith('\t') ? ` ${line}` : line);
        }
        else if (line.trim() === '') {
            diffLines.push(' ');
            addCount++;
            removeCount++;
        }
        else {
            addCount++;
            removeCount++;
            diffLines.push(` ${line}`);
        }
    }
    if (diffLines.length > 0) {
        result.push(`@@ -1,${removeCount} +1,${addCount} @@`);
        result.push(...diffLines);
    }
    return result.join('\n');
}
function getLanguageFromPath(path) {
    const ext = path.split('.').pop()?.toLowerCase();
    const langMap = {
        js: 'javascript',
        jsx: 'jsx',
        ts: 'typescript',
        tsx: 'tsx',
        py: 'python',
        rb: 'ruby',
        go: 'go',
        rs: 'rust',
        java: 'java',
        c: 'c',
        cpp: 'cpp',
        h: 'c',
        hpp: 'cpp',
        cs: 'csharp',
        php: 'php',
        sh: 'bash',
        bash: 'bash',
        zsh: 'bash',
        sql: 'sql',
        json: 'json',
        yaml: 'yaml',
        yml: 'yaml',
        xml: 'xml',
        html: 'html',
        css: 'css',
        scss: 'scss',
        md: 'markdown',
        txt: 'text',
        svelte: 'svelte',
    };
    return langMap[ext || ''] || 'javascript';
}
function parseDiff(patch) {
    const lines = patch.split('\n');
    const result = [];
    let oldLineNum = 0;
    let newLineNum = 0;
    let inHunk = false;
    let filePath = '';
    for (const line of lines) {
        if (line.startsWith('+++') || line.startsWith('*** Update File:')) {
            const match = line.match(/\+\+\+ b\/(.+)/) || line.match(/\*\*\* Update File: (.+)/);
            if (match)
                filePath = match[1];
        }
        if (line.startsWith('*** Add File:')) {
            const match = line.match(/\*\*\* Add File: (.+)/);
            if (match)
                filePath = match[1];
        }
        const hunkMatch = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
        if (hunkMatch) {
            oldLineNum = Number.parseInt(hunkMatch[1], 10);
            newLineNum = Number.parseInt(hunkMatch[2], 10);
            inHunk = true;
            result.push({
                content: line,
                codeContent: line,
                type: 'header',
            });
            continue;
        }
        if (line.startsWith('***') ||
            line.startsWith('diff ') ||
            line.startsWith('index ') ||
            line.startsWith('---') ||
            line.startsWith('+++') ||
            (line.startsWith('@@') && !inHunk)) {
            result.push({
                content: line,
                codeContent: line,
                type: 'meta',
            });
            continue;
        }
        if (inHunk) {
            if (line.startsWith('+')) {
                result.push({
                    content: line,
                    codeContent: line.slice(1),
                    type: 'add',
                    newLineNum: newLineNum++,
                });
            }
            else if (line.startsWith('-')) {
                result.push({
                    content: line,
                    codeContent: line.slice(1),
                    type: 'remove',
                    oldLineNum: oldLineNum++,
                });
            }
            else if (line.startsWith(' ') || line === '') {
                result.push({
                    content: line,
                    codeContent: line.startsWith(' ') ? line.slice(1) : line,
                    type: 'context',
                    oldLineNum: oldLineNum++,
                    newLineNum: newLineNum++,
                });
            }
            else {
                result.push({
                    content: line,
                    codeContent: line,
                    type: 'context',
                    oldLineNum: oldLineNum++,
                    newLineNum: newLineNum++,
                });
            }
        }
        else {
            result.push({
                content: line,
                codeContent: line,
                type: 'meta',
            });
        }
    }
    return { lines: result, filePath };
}
function FullHeightDiffView({ patch }) {
    const { lines: diffLines, filePath } = parseDiff(patch);
    const language = getLanguageFromPath(filePath);
    const syntaxTheme = document?.documentElement.classList.contains('dark')
        ? vscDarkPlus
        : prism;
    return (_jsx("div", { className: "bg-card/60 border border-border rounded-lg overflow-hidden h-full", children: _jsx("div", { className: "overflow-x-auto overflow-y-auto h-full text-xs font-mono", children: diffLines.map((line, i) => {
                const key = `line-${i}-${line.content.slice(0, 20)}`;
                if (line.type === 'meta' || line.type === 'header') {
                    return (_jsx("div", { className: `px-3 py-0.5 whitespace-pre-wrap break-all ${line.type === 'header'
                            ? 'text-muted-foreground/80 bg-muted/20'
                            : 'text-muted-foreground/80'}`, children: line.content }, key));
                }
                let lineClass = '';
                let bgClass = '';
                switch (line.type) {
                    case 'add':
                        lineClass = 'text-emerald-700 dark:text-emerald-300';
                        bgClass = 'bg-emerald-500/10';
                        break;
                    case 'remove':
                        lineClass = 'text-red-600 dark:text-red-300';
                        bgClass = 'bg-red-500/10';
                        break;
                    default:
                        lineClass = 'text-foreground/80';
                }
                let renderedContent = line.content;
                if (line.codeContent.trim() && language !== 'text') {
                    renderedContent = (_jsx(SyntaxHighlighter, { language: language, style: syntaxTheme, customStyle: {
                            margin: 0,
                            padding: 0,
                            background: 'transparent',
                            display: 'inline',
                            fontSize: 'inherit',
                            lineHeight: 'inherit',
                        }, codeTagProps: {
                            style: {
                                fontFamily: 'inherit',
                                background: 'transparent',
                            },
                        }, PreTag: "span", children: line.codeContent }));
                    if (line.type === 'add') {
                        renderedContent = (_jsxs(_Fragment, { children: [_jsx("span", { className: "select-none", children: "+" }), renderedContent] }));
                    }
                    else if (line.type === 'remove') {
                        renderedContent = (_jsxs(_Fragment, { children: [_jsx("span", { className: "select-none", children: "-" }), renderedContent] }));
                    }
                    else if (line.type === 'context') {
                        renderedContent = (_jsxs(_Fragment, { children: [_jsx("span", { className: "select-none", children: " " }), renderedContent] }));
                    }
                }
                return (_jsxs("div", { className: `flex ${bgClass}`, children: [_jsx("div", { className: "px-2 py-0.5 text-right text-muted-foreground/40 select-none w-12 flex-shrink-0", children: line.oldLineNum || '' }), _jsx("div", { className: "px-2 py-0.5 text-right text-muted-foreground/40 select-none w-12 flex-shrink-0 border-r border-border/50", children: line.newLineNum || '' }), _jsx("div", { className: `px-3 py-0.5 flex-1 min-w-0 whitespace-pre-wrap break-all ${lineClass}`, children: renderedContent })] }, key));
            }) }) }));
}
function formatTimestamp(timestamp) {
    const date = new Date(timestamp);
    return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
export const SessionFilesDiffPanel = memo(function SessionFilesDiffPanel() {
    const isDiffOpen = useSessionFilesStore((state) => state.isDiffOpen);
    const selectedFile = useSessionFilesStore((state) => state.selectedFile);
    const allOperations = useSessionFilesStore((state) => state.allOperations);
    const selectedOperationIndex = useSessionFilesStore((state) => state.selectedOperationIndex);
    const selectOperation = useSessionFilesStore((state) => state.selectOperation);
    const closeDiff = useSessionFilesStore((state) => state.closeDiff);
    const setCollapsed = useSidebarStore((state) => state.setCollapsed);
    const wasCollapsedRef = useRef(null);
    const prevDiffOpenRef = useRef(false);
    const selectedOperation = allOperations[selectedOperationIndex];
    const patchContent = useMemo(() => {
        if (!selectedOperation || !selectedFile)
            return null;
        let rawPatch = null;
        if (selectedOperation.artifact?.patch) {
            rawPatch = selectedOperation.artifact.patch;
        }
        else if (selectedOperation.patch) {
            rawPatch = selectedOperation.patch;
        }
        else if (selectedOperation.content) {
            const contentLines = selectedOperation.content.split('\n');
            rawPatch = `*** Add File: ${selectedFile}\n${contentLines.map((line) => `+${line}`).join('\n')}`;
        }
        if (!rawPatch)
            return null;
        const hasProperHunkHeader = /@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/.test(rawPatch);
        if (!hasProperHunkHeader) {
            return transformToUnifiedDiff(rawPatch);
        }
        return rawPatch;
    }, [selectedOperation, selectedFile]);
    useEffect(() => {
        // Only act on transitions
        if (isDiffOpen && !prevDiffOpenRef.current) {
            // Diff just opened - save current state and collapse
            const { isCollapsed } = useSidebarStore.getState();
            wasCollapsedRef.current = isCollapsed;
            setCollapsed(true);
        }
        else if (!isDiffOpen && prevDiffOpenRef.current) {
            // Diff just closed - restore previous state
            if (wasCollapsedRef.current !== null) {
                setCollapsed(wasCollapsedRef.current);
                wasCollapsedRef.current = null;
            }
        }
        prevDiffOpenRef.current = isDiffOpen;
    }, [isDiffOpen, setCollapsed]);
    useEffect(() => {
        const handleKeyDown = (e) => {
            const target = e.target;
            const isInInput = target.tagName === 'INPUT' ||
                target.tagName === 'TEXTAREA' ||
                target.isContentEditable;
            if ((e.key === 'Escape' || (e.key === 'q' && !isInInput)) && isDiffOpen) {
                closeDiff();
            }
            if (!isInInput && isDiffOpen && allOperations.length > 1) {
                if (e.key === 'ArrowLeft' || e.key === '[') {
                    e.preventDefault();
                    selectOperation(Math.max(0, selectedOperationIndex - 1));
                }
                else if (e.key === 'ArrowRight' || e.key === ']') {
                    e.preventDefault();
                    selectOperation(Math.min(allOperations.length - 1, selectedOperationIndex + 1));
                }
            }
        };
        document.addEventListener('keydown', handleKeyDown);
        return () => document.removeEventListener('keydown', handleKeyDown);
    }, [
        isDiffOpen,
        closeDiff,
        allOperations.length,
        selectedOperationIndex,
        selectOperation,
    ]);
    if (!isDiffOpen || !selectedFile || !selectedOperation)
        return null;
    const hasMultipleOps = allOperations.length > 1;
    return (_jsxs("div", { className: "absolute inset-0 bg-background z-50 flex flex-col animate-in slide-in-from-left duration-300", children: [_jsxs("div", { className: "h-14 border-b border-border px-4 flex items-center gap-3 shrink-0", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: closeDiff, title: "Close diff viewer (ESC)", children: _jsx(X, { className: "w-4 h-4" }) }), _jsxs("div", { className: "flex-1 flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "text-sm font-medium text-foreground font-mono truncate", title: selectedFile, children: selectedFile }), _jsx("span", { className: "text-xs px-2 py-0.5 rounded bg-primary/10 text-primary flex-shrink-0 capitalize", children: selectedOperation.operation }), selectedOperation.artifact?.summary && (_jsxs("div", { className: "flex items-center gap-1 text-xs flex-shrink-0", children: [_jsxs("span", { className: "text-green-500", children: ["+", selectedOperation.artifact.summary.additions] }), _jsxs("span", { className: "text-red-500", children: ["-", selectedOperation.artifact.summary.deletions] })] }))] }), hasMultipleOps && (_jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [_jsx(Button, { variant: "ghost", size: "icon", onClick: () => selectOperation(Math.max(0, selectedOperationIndex - 1)), disabled: selectedOperationIndex === 0, title: "Previous operation (\u2190)", children: _jsx(ChevronLeft, { className: "w-4 h-4" }) }), _jsxs("span", { className: "text-xs text-muted-foreground min-w-[60px] text-center", children: [selectedOperationIndex + 1, " / ", allOperations.length] }), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => selectOperation(Math.min(allOperations.length - 1, selectedOperationIndex + 1)), disabled: selectedOperationIndex === allOperations.length - 1, title: "Next operation (\u2192)", children: _jsx(ChevronRight, { className: "w-4 h-4" }) })] }))] }), hasMultipleOps && (_jsx("div", { className: "border-b border-border px-4 py-2 flex gap-2 overflow-x-auto shrink-0", children: allOperations.map((op, idx) => (_jsxs("button", { type: "button", onClick: () => selectOperation(idx), className: `px-3 py-1.5 text-xs rounded-md flex items-center gap-2 shrink-0 transition-colors ${idx === selectedOperationIndex
                        ? 'bg-primary text-primary-foreground'
                        : 'bg-muted hover:bg-muted/80 text-muted-foreground'}`, children: [_jsx("span", { className: "capitalize", children: op.operation }), _jsx("span", { className: "opacity-70", children: formatTimestamp(op.timestamp) }), op.artifact?.summary && (_jsxs("span", { className: "opacity-70", children: ["+", op.artifact.summary.additions, "/-", op.artifact.summary.deletions] }))] }, op.toolCallId))) })), _jsx("div", { className: "flex-1 overflow-hidden p-4", children: patchContent ? (_jsx(FullHeightDiffView, { patch: patchContent })) : (_jsx("div", { className: "h-full flex items-center justify-center text-muted-foreground", children: "No diff content available" })) })] }));
});
//# sourceMappingURL=SessionFilesDiffPanel.js.map