import React, { useEffect, useMemo, useRef } from 'react';
import * as monaco from 'monaco-editor';
import { Dialog } from '@/components/elements/dialog';
import { Button } from '@/components/elements/button/index';
import GreyRowBox from '@/components/elements/GreyRowBox';
import { getMonacoLanguageFromFilename } from '../../SimpleEditor';

interface Props {
    open: boolean;
    filePath: string;
    originalContent: string;
    modifiedContent: string;
    onClose: () => void;
}

interface EditorDiffViewProps {
    filePath: string;
    originalContent: string;
    modifiedContent: string;
    className?: string;
    style?: React.CSSProperties;
}

const getChangeStats = (originalContent: string, modifiedContent: string) => {
    const originalLines = originalContent.split('\n');
    const modifiedLines = modifiedContent.split('\n');
    let changed = 0;

    for (let index = 0; index < Math.max(originalLines.length, modifiedLines.length); index += 1) {
        if (originalLines[index] !== modifiedLines[index]) changed += 1;
    }

    return changed;
};

export const EditorDiffView: React.FC<EditorDiffViewProps> = ({
    filePath,
    originalContent,
    modifiedContent,
    className,
    style,
}) => {
    const containerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (!containerRef.current) return;

        const language = getMonacoLanguageFromFilename(filePath);
        const suffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
        const originalModel = monaco.editor.createModel(
            originalContent,
            language,
            monaco.Uri.parse(`inmemory://betterfiles-diff/original/${suffix}`)
        );
        const modifiedModel = monaco.editor.createModel(
            modifiedContent,
            language,
            monaco.Uri.parse(`inmemory://betterfiles-diff/modified/${suffix}`)
        );

        const editor = monaco.editor.createDiffEditor(containerRef.current, {
            theme: 'betterfiles-dark',
            readOnly: true,
            automaticLayout: true,
            renderSideBySide: true,
            minimap: { enabled: true, autohide: true, showSlider: 'mouseover', renderCharacters: false },
            scrollbar: {
                alwaysConsumeMouseWheel: false,
                horizontal: 'auto',
                vertical: 'auto',
                useShadows: false,
            },
            smoothScrolling: false,
            scrollBeyondLastLine: false,
        });

        editor.setModel({ original: originalModel, modified: modifiedModel });

        window.setTimeout(() => editor.layout(), 75);

        return () => {
            editor.dispose();
            originalModel.dispose();
            modifiedModel.dispose();
        };
    }, [filePath, modifiedContent, originalContent]);

    return <div ref={containerRef} className={className || 'w-full min-w-0'} style={style} />;
};

const EditorDiffDialog: React.FC<Props> = ({ open, filePath, originalContent, modifiedContent, onClose }) => {
    const changeCount = useMemo(
        () => getChangeStats(originalContent, modifiedContent),
        [originalContent, modifiedContent]
    );

    return (
        <Dialog open={open} onClose={onClose} title='Changes'>
            <div className='space-y-3'>
                <div className='text-sm text-neutral-300'>
                    {changeCount === 0 ? 'No changes found.' : `${changeCount} changed line${changeCount === 1 ? '' : 's'}.`}
                </div>
                <GreyRowBox className='!p-0 overflow-hidden !items-stretch' $hoverable={false}>
                    {open && (
                        <EditorDiffView
                            filePath={filePath}
                            originalContent={originalContent}
                            modifiedContent={modifiedContent}
                            className='w-full min-w-0'
                            style={{ height: 'min(70vh, 620px)' }}
                        />
                    )}
                </GreyRowBox>
            </div>
            <Dialog.Footer>
                <Button.Text onClick={onClose}>Close</Button.Text>
            </Dialog.Footer>
        </Dialog>
    );
};

export default EditorDiffDialog;
