import { useCallback, useMemo, useState } from 'react';
import { open } from '@tauri-apps/plugin-dialog';

import { TopBar } from '../components/topbar/TopBar';
import { KebabItem } from '../components/topbar/KebabMenu';
import { ResultsBar } from '../components/grid/ResultsBar';
import { GameGrid } from '../components/grid/GameGrid';
import { GameDetailModal } from '../components/modals/GameDetailModal';
import { ConfirmRemoveDownloadModal } from '../components/modals/ConfirmRemoveDownloadModal';
import { SettingsDialog } from '../components/modals/SettingsDialog';
import { NoDirectoryState } from '../components/empty/NoDirectoryState';
import { EmptyResultsState } from '../components/empty/EmptyResultsState';

import { useGameDirectory } from '../hooks/useGameDirectory';
import { useGames } from '../hooks/useGames';
import { useGameActions } from '../hooks/useGameActions';
import { useThumbnails } from '../hooks/useThumbnails';
import { useSettings } from '../hooks/useSettings';

import { Game } from '../lib/types';
import { applyFilterAndSort, countByFilter, needsUpdate } from '../lib/gameState';

const openLogsWindow = async () => {
    const { WebviewWindow } = await import('@tauri-apps/api/webviewWindow');
    try {
        const existing = await WebviewWindow.getByLabel('unpack-logs');
        if (existing) {
            await existing.setFocus();
            return;
        }
        const win = new WebviewWindow('unpack-logs', {
            url: '/?view=unpack-logs',
            title: 'Unpack Logs',
            width: 900,
            height: 700,
            resizable: true,
        });
        await win.once<unknown>('tauri://error', (event) => {
            console.error('Error opening unpack logs window:', event.payload);
        });
    } catch (err) {
        console.error('Error opening unpack logs window:', err);
    }
};

export const MainWindow = () => {
    const { settings, set: setSetting } = useSettings();
    const { gameDir, setGameDir, rescan } = useGameDirectory();
    const games = useGames(rescan);
    const actions = useGameActions(games);
    const thumbnails = useThumbnails();

    const [openGameId, setOpenGameId] = useState<string | null>(null);
    const [removeGameId, setRemoveGameId] = useState<string | null>(null);
    const [settingsOpen, setSettingsOpen] = useState(false);

    const counts = useMemo(() => countByFilter(games.games), [games.games]);

    // Query is local UI state (no need to persist).
    const [query, setQuery] = useState('');
    const filteredGames = useMemo(
        () => applyFilterAndSort(games.games, settings.filter, settings.sort, query),
        [games.games, settings.filter, settings.sort, query],
    );

    const openGame = useMemo<Game | null>(
        () => openGameId ? games.games.find(g => g.id === openGameId) ?? null : null,
        [openGameId, games.games],
    );
    const removeGame = useMemo<Game | null>(
        () => removeGameId ? games.games.find(g => g.id === removeGameId) ?? null : null,
        [removeGameId, games.games],
    );

    const pickDirectory = useCallback(async () => {
        const picked = await open({ multiple: false, directory: true });
        if (typeof picked === 'string' && picked) setGameDir(picked);
    }, [setGameDir]);

    const handlePrimary = useCallback((game: Game) => {
        if (game.installed) {
            if (needsUpdate(game)) actions.update(game.id);
            else actions.play(game.id);
        } else {
            actions.install(game.id);
        }
    }, [actions]);

    const handleUninstall = useCallback((game: Game) => {
        actions.uninstall(game.id);
    }, [actions]);

    const handleRemoveDownload = useCallback((game: Game) => {
        setRemoveGameId(game.id);
    }, []);

    const confirmRemoveDownload = useCallback((game: Game) => {
        actions.removeDownload(game.id);
        setRemoveGameId(null);
        setOpenGameId(current => current === game.id ? null : current);
    }, [actions]);

    const kebabItems: ReadonlyArray<KebabItem> = useMemo(() => [
        { kind: 'item', label: 'Settings', onClick: () => setSettingsOpen(true) },
        { kind: 'item', label: 'Refresh library', onClick: () => rescan() },
        { kind: 'separator' },
        { kind: 'item', label: 'Unpack logs', onClick: () => void openLogsWindow() },
    ], [rescan]);

    const rootStyle = { '--accent': settings.accent } as React.CSSProperties;
    const className = [
        'launcher',
        `bg-${settings.bg}`,
        `density-${settings.density}`,
    ].join(' ');

    return (
        <div className={className} style={rootStyle}>
            {gameDir ? (
                <>
                    <TopBar
                        peerCount={games.totalPeerCount}
                        filter={settings.filter}
                        setFilter={(v) => setSetting('filter', v)}
                        counts={counts}
                        query={query}
                        setQuery={setQuery}
                        sort={settings.sort}
                        setSort={(v) => setSetting('sort', v)}
                        gameDir={gameDir}
                        onPickDirectory={() => void pickDirectory()}
                        kebabItems={kebabItems}
                    />
                    <main className="grid-wrap">
                        <ResultsBar shown={filteredGames.length} total={counts.all} />
                        {filteredGames.length === 0 ? (
                            games.games.length === 0 ? (
                                <EmptyResultsState
                                    title="Scanning for games"
                                    hint="Looking for game bundles in your selected directory…"
                                />
                            ) : (
                                <EmptyResultsState
                                    title="Nothing matches"
                                    hint="No games match the current filter or search query."
                                />
                            )
                        ) : (
                            <GameGrid
                                games={filteredGames}
                                aspect={settings.aspect}
                                getThumbnail={thumbnails.get}
                                onOpen={(g) => setOpenGameId(g.id)}
                                onPrimary={handlePrimary}
                            />
                        )}
                    </main>
                </>
            ) : (
                <main className="grid-wrap">
                    <NoDirectoryState onChooseDirectory={() => void pickDirectory()} />
                </main>
            )}

            {openGame && (
                <GameDetailModal
                    game={openGame}
                    thumbnailUrl={thumbnails.get(openGame.id)}
                    onClose={() => setOpenGameId(null)}
                    onPrimary={handlePrimary}
                    onUninstall={handleUninstall}
                    onRemoveDownload={handleRemoveDownload}
                />
            )}

            {removeGame && (
                <ConfirmRemoveDownloadModal
                    game={removeGame}
                    onCancel={() => setRemoveGameId(null)}
                    onConfirm={confirmRemoveDownload}
                />
            )}

            {settingsOpen && (
                <SettingsDialog
                    settings={settings}
                    onChange={setSetting}
                    onClose={() => setSettingsOpen(false)}
                />
            )}
        </div>
    );
};
