import { GridComponent } from '@/components/grid/GridComponent';
import { ColorSwatch } from '@/components/toolbar/ColorSwatch';
import { Toolbar } from '@/components/toolbar/Toolbar';
import { ToolbarItem } from '@/components/toolbar/ToolbarItem';
import { SaveModal } from '@/components/SaveModal';
import type { AnsiTermColor, Grid, GridCell } from '@/types/grid';
import { gridToAnsi } from '@/utils/grid';
import { saveArt } from '@/utils/storage';
import { type IZipper, ListZipper } from '@emprespresso/pengueno';
import { useCallback, useEffect, useState } from 'react';
import { flushSync } from 'react-dom';

export interface ChooseArtProps {
    grid: Grid;
    onGoHome?: () => void;
}

// Gruvbox theme colors converted to ANSI RGB values
const defaultColors: AnsiTermColor[] = [
    { foreground: { r: 5, g: 5, b: 5 }, background: null }, // bright7 #ebdbb2
    { foreground: { r: 5, g: 1, b: 1 }, background: null }, // regular1 #cc241d
    { foreground: { r: 4, g: 4, b: 1 }, background: null }, // regular2 #98971a
    { foreground: { r: 5, g: 4, b: 1 }, background: null }, // regular3 #d79921
    { foreground: { r: 2, g: 3, b: 4 }, background: null }, // regular4 #458588
    { foreground: { r: 4, g: 2, b: 3 }, background: null }, // regular5 #b16286
    { foreground: { r: 3, g: 4, b: 3 }, background: null }, // regular6 #689d6a
    { foreground: { r: 4, g: 4, b: 3 }, background: null }, // regular7 #a89984
];

export const Paint: React.FC<ChooseArtProps> = ({ grid, onGoHome }) => {
    const [showSaveModal, setShowSaveModal] = useState(false);
    const [selectedColor, setSelectedColor] = useState<AnsiTermColor>({
        foreground: { r: 5, g: 5, b: 5 },
        background: null,
    });
    const [history, setHistory] = useState<IZipper<Grid>>(
        ListZipper.from([grid]),
    );
    const [isDragging, setIsDragging] = useState(false);
    const [workingGrid, setWorkingGrid] = useState<Grid>(grid);

    const handleDragStart = useCallback(() => {
        setIsDragging(true);
        // Don't reset workingGrid here - let it accumulate changes
    }, []);

    const handleDragEnd = useCallback(() => {
        if (isDragging) {
            // Commit the working grid to history as a single atomic operation
            setHistory((currentHistory) => {
                return currentHistory.prepend(workingGrid).previous().get();
            });
            setIsDragging(false);
        }
    }, [isDragging, workingGrid]);

    const cellInteractionCallback = useCallback(
        (cell: GridCell) => {
            flushSync(() => {
                setWorkingGrid((currentGrid) => {
                    const newGrid = currentGrid.map((row) => [...row]);
                    newGrid[cell.y][cell.x] = { ...cell, color: selectedColor };
                    return newGrid;
                });
            });
        },
        [selectedColor],
    );

    const handleSave = (name: string) => {
        const currentGrid = history.read().get();
        saveArt(name, currentGrid);
    };

    const currentGrid = workingGrid;
    const ansiOutput = gridToAnsi(currentGrid);

    return (
        <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
            {showSaveModal && (
                <SaveModal
                    ansiOutput={ansiOutput}
                    onSave={handleSave}
                    onClose={() => setShowSaveModal(false)}
                />
            )}
            <Toolbar>
                <ToolbarItem
                    renderContent={(onClose) => (
                        <ColorSwatch
                            onSelect={setSelectedColor}
                            onClose={onClose}
                            defaultColors={defaultColors}
                        ></ColorSwatch>
                    )}
                >
                    🎨
                </ToolbarItem>
                <ToolbarItem
                    disabled={
                        !history
                            .previous()
                            .flatMap((it) => it.read())
                            .present()
                    }
                    onClick={() => {
                        setHistory((history) => {
                            const newHistory = history.previous().get();
                            setWorkingGrid(newHistory.read().get());
                            return newHistory;
                        });
                    }}
                >
                    ↷
                </ToolbarItem>
                <ToolbarItem
                    disabled={
                        !history
                            .next()
                            .flatMap((it) => it.read())
                            .present()
                    }
                    onClick={() => {
                        setHistory((history) => {
                            const newHistory = history.next().get();
                            setWorkingGrid(newHistory.read().get());
                            return newHistory;
                        });
                    }}
                >
                    ↶
                </ToolbarItem>
                <ToolbarItem onClick={() => setShowSaveModal(true)}>
                    💾
                </ToolbarItem>
                <ToolbarItem onClick={onGoHome}>
                    🏠
                </ToolbarItem>
            </Toolbar>
            <GridComponent
                grid={currentGrid}
                onCellInteract={cellInteractionCallback}
                onDragStart={handleDragStart}
                onDragEnd={handleDragEnd}
            />
        </div>
    );
};
