import React, { useEffect, useMemo, useState } from 'react';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Input from '@/components/elements/Input';
import Select from '@/components/elements/Select';
import Spinner from '@/components/elements/Spinner';
import { Button } from '@/components/elements/button/index';
import { Dialog } from '@/components/elements/dialog';
import { themeColors } from './colorExtractor';
import {
    DatabaseCreateColumn,
    DatabaseInspectResponse,
    DatabaseRow,
    DatabaseTableResponse,
    DatabaseTableSummary,
    createDatabaseTable,
    deleteDatabaseRow,
    initializeDatabaseFile,
    insertDatabaseRow,
    inspectDatabaseFile,
    readDatabaseTable,
    updateDatabaseCell,
} from './api/server/files/betterFilesApi';
import { FaCopy, FaDatabase, FaEdit, FaPlus, FaSearch, FaTable, FaTrash } from 'react-icons/fa';

interface DatabaseViewerProps {
    uuid: string;
    filePath: string;
    readOnly?: boolean;
}

const cx = (...classes: Array<string | false | null | undefined>): string => classes.filter(Boolean).join(' ');

const viewerPanelStyle: React.CSSProperties = {
    backgroundColor: themeColors.page.background,
    borderColor: themeColors.page.secondaryHover,
};

const viewerHeaderStyle: React.CSSProperties = {
    backgroundColor: themeColors.page.secondary,
    borderColor: themeColors.page.secondaryHover,
};

const viewerBodyStyle: React.CSSProperties = {
    backgroundColor: themeColors.page.background,
};

const formatCell = (value: string | number | null): string => {
    if (value === null || typeof value === 'undefined') return 'NULL';
    return String(value);
};

const tableLabel = (table: DatabaseTableSummary): string => table.type === 'view' ? 'View' : 'Table';

interface EditingCell {
    rowId: number;
    column: string;
    value: string;
    originalValue: string;
}

type RowEditorMode = 'insert' | 'edit' | 'duplicate';

const databaseColumnTypes: DatabaseCreateColumn['type'][] = ['TEXT', 'INTEGER', 'INTEGER PRIMARY KEY', 'REAL', 'BLOB', 'NUMERIC'];

const DatabaseViewer: React.FC<DatabaseViewerProps> = ({ uuid, filePath, readOnly = false }) => {
    const [database, setDatabase] = useState<DatabaseInspectResponse | null>(null);
    const [tableData, setTableData] = useState<DatabaseTableResponse | null>(null);
    const [activeTable, setActiveTable] = useState('');
    const [searchDraft, setSearchDraft] = useState('');
    const [search, setSearch] = useState('');
    const [page, setPage] = useState(1);
    const [perPage, setPerPage] = useState(25);
    const [loading, setLoading] = useState(false);
    const [tableLoading, setTableLoading] = useState(false);
    const [initializing, setInitializing] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [tableError, setTableError] = useState<string | null>(null);
    const [tableRefreshKey, setTableRefreshKey] = useState(0);
    const [editingCell, setEditingCell] = useState<EditingCell | null>(null);
    const [rowEditorMode, setRowEditorMode] = useState<RowEditorMode | null>(null);
    const [editingRowId, setEditingRowId] = useState<number | null>(null);
    const [showCreateTableDialog, setShowCreateTableDialog] = useState(false);
    const [createTableName, setCreateTableName] = useState('');
    const [createTableColumns, setCreateTableColumns] = useState<DatabaseCreateColumn[]>([
        { name: 'id', type: 'INTEGER PRIMARY KEY' },
        { name: 'name', type: 'TEXT' },
    ]);
    const [deleteRowId, setDeleteRowId] = useState<number | null>(null);
    const [newRowValues, setNewRowValues] = useState<Record<string, string>>({});
    const [savingMutation, setSavingMutation] = useState(false);
    const [mutationError, setMutationError] = useState<string | null>(null);

    const fileName = filePath.substring(filePath.lastIndexOf('/') + 1);

    const loadDatabase = () => {
        setLoading(true);
        setError(null);
        setDatabase(null);
        setTableData(null);
        setActiveTable('');
        setSearchDraft('');
        setSearch('');
        setPage(1);
        setMutationError(null);
        setEditingCell(null);
        setRowEditorMode(null);
        setEditingRowId(null);
        setShowCreateTableDialog(false);
        setDeleteRowId(null);

        return inspectDatabaseFile(uuid, filePath)
            .then((response) => {
                setDatabase(response);
                setActiveTable(response.tables[0]?.name || '');
            })
            .catch((error) => {
                setError(error?.response?.data?.error || error?.message || 'Could not inspect database.');
            })
            .finally(() => setLoading(false));
    };

    useEffect(() => {
        let mounted = true;

        setLoading(true);
        setError(null);
        setDatabase(null);
        setTableData(null);
        setActiveTable('');
        setSearchDraft('');
        setSearch('');
        setPage(1);
        setMutationError(null);
        setEditingCell(null);
        setRowEditorMode(null);
        setEditingRowId(null);
        setShowCreateTableDialog(false);
        setDeleteRowId(null);

        inspectDatabaseFile(uuid, filePath)
            .then((response) => {
                if (!mounted) return;
                setDatabase(response);
                setActiveTable(response.tables[0]?.name || '');
            })
            .catch((error) => {
                if (!mounted) return;
                setError(error?.response?.data?.error || error?.message || 'Could not inspect database.');
            })
            .finally(() => {
                if (mounted) setLoading(false);
            });

        return () => {
            mounted = false;
        };
    }, [filePath, uuid]);

    const handleInitialize = () => {
        if (readOnly) return;
        setInitializing(true);
        setError(null);

        initializeDatabaseFile(uuid, filePath)
            .then((response) => {
                setDatabase(response);
                setTableData(null);
                setActiveTable(response.tables[0]?.name || '');
                setMutationError(null);
            })
            .catch((error) => {
                setError(error?.response?.data?.error || error?.message || 'Could not initialize database.');
            })
            .finally(() => setInitializing(false));
    };

    useEffect(() => {
        const timer = window.setTimeout(() => {
            setPage(1);
            setSearch(searchDraft.trim());
        }, 250);

        return () => window.clearTimeout(timer);
    }, [searchDraft]);

    useEffect(() => {
        if (!activeTable) return;

        let mounted = true;
        setTableLoading(true);
        setTableError(null);
        setMutationError(null);

        readDatabaseTable(uuid, filePath, activeTable, page, perPage, search)
            .then((response) => {
                if (!mounted) return;
                setTableData(response);
            })
            .catch((error) => {
                if (!mounted) return;
                setTableError(error?.response?.data?.error || error?.message || 'Could not read table.');
            })
            .finally(() => {
                if (mounted) setTableLoading(false);
            });

        return () => {
            mounted = false;
        };
    }, [activeTable, filePath, page, perPage, search, tableRefreshKey, uuid]);

    const activeSummary = useMemo(
        () => database?.tables.find((table) => table.name === activeTable),
        [activeTable, database]
    );

    const pagination = tableData?.pagination;
    const canPrevious = !!pagination && pagination.current_page > 1;
    const canNext = !!pagination && pagination.current_page < pagination.total_pages;
    const editableColumns = useMemo(
        () => tableData?.columns.filter((column) => !column.primary_key) || [],
        [tableData]
    );

    const refreshTable = () => setTableRefreshKey((value) => value + 1);

    const databaseError = (error: any, fallback: string) =>
        error?.response?.data?.error || error?.message || fallback;

    const rowValuesFromRow = (row: DatabaseRow): Record<string, string> => Object.fromEntries(
        editableColumns.map((column) => {
            const value = row[column.name];
            return [column.name, value === null || typeof value === 'undefined' ? '' : String(value)];
        })
    );

    const openCellEditor = (rowId: number, column: string, value: string | number | null) => {
        if (readOnly) return;
        const stringValue = value === null || typeof value === 'undefined' ? '' : String(value);

        setMutationError(null);
        setEditingCell({
            rowId,
            column,
            value: stringValue,
            originalValue: stringValue,
        });
    };

    const openInsertDialog = () => {
        if (readOnly) return;
        if (!tableData) return;

        setMutationError(null);
        setEditingRowId(null);
        setNewRowValues(Object.fromEntries(editableColumns.map((column) => [column.name, ''])));
        setRowEditorMode('insert');
    };

    const openEditRowDialog = (row: DatabaseRow, rowId: number) => {
        if (readOnly) return;
        setMutationError(null);
        setEditingRowId(rowId);
        setNewRowValues(rowValuesFromRow(row));
        setRowEditorMode('edit');
    };

    const openDuplicateRowDialog = (row: DatabaseRow) => {
        if (readOnly) return;
        setMutationError(null);
        setEditingRowId(null);
        setNewRowValues(rowValuesFromRow(row));
        setRowEditorMode('duplicate');
    };

    const openCreateTableDialog = () => {
        if (readOnly) return;
        setMutationError(null);
        setCreateTableName('');
        setCreateTableColumns([
            { name: 'id', type: 'INTEGER PRIMARY KEY' },
            { name: 'name', type: 'TEXT' },
        ]);
        setShowCreateTableDialog(true);
    };

    const handleCreateTable = () => {
        if (readOnly) return;
        const name = createTableName.trim();
        const columns = createTableColumns
            .map((column) => ({ name: column.name.trim(), type: column.type }))
            .filter((column) => column.name.length > 0);

        if (!name || columns.length === 0) {
            setMutationError('A table name and at least one column are required.');
            return;
        }

        setSavingMutation(true);
        setMutationError(null);

        createDatabaseTable(uuid, filePath, name, columns)
            .then(() => inspectDatabaseFile(uuid, filePath))
            .then((response) => {
                setDatabase(response);
                setActiveTable(name);
                setPage(1);
                setShowCreateTableDialog(false);
                refreshTable();
            })
            .catch((error) => setMutationError(databaseError(error, 'Could not create database table.')))
            .finally(() => setSavingMutation(false));
    };

    const handleSaveCell = (value: string | number | null = editingCell?.value ?? null) => {
        if (readOnly) return;
        if (!editingCell || !activeTable || savingMutation) return;

        if (value !== null && value === editingCell.originalValue) {
            setEditingCell(null);
            return;
        }

        setSavingMutation(true);
        setMutationError(null);

        updateDatabaseCell(uuid, filePath, activeTable, editingCell.rowId, editingCell.column, value)
            .then(() => {
                setEditingCell(null);
                refreshTable();
            })
            .catch((error) => setMutationError(databaseError(error, 'Could not update database cell.')))
            .finally(() => setSavingMutation(false));
    };

    const handleSaveRow = () => {
        if (readOnly) return;
        if (!activeTable || !rowEditorMode) return;

        const values = Object.fromEntries(
            Object.entries(newRowValues)
                .map(([key, value]) => [key, value.trim()] as const)
                .filter(([, value]) => rowEditorMode === 'edit' || value.length > 0)
        );

        setSavingMutation(true);
        setMutationError(null);

        const request = rowEditorMode === 'edit' && editingRowId
            ? Promise.all(Object.entries(values).map(([column, value]) => (
                updateDatabaseCell(uuid, filePath, activeTable, editingRowId, column, value)
            ))).then(() => undefined)
            : insertDatabaseRow(uuid, filePath, activeTable, values);

        request
            .then(() => {
                setRowEditorMode(null);
                setEditingRowId(null);
                setNewRowValues({});
                refreshTable();
            })
            .catch((error) => setMutationError(databaseError(error, rowEditorMode === 'edit' ? 'Could not update database row.' : 'Could not insert database row.')))
            .finally(() => setSavingMutation(false));
    };

    const handleDeleteRow = () => {
        if (readOnly) return;
        if (!activeTable || !deleteRowId) return;

        setSavingMutation(true);
        setMutationError(null);

        deleteDatabaseRow(uuid, filePath, activeTable, deleteRowId)
            .then(() => {
                setDeleteRowId(null);
                refreshTable();
            })
            .catch((error) => setMutationError(databaseError(error, 'Could not delete database row.')))
            .finally(() => setSavingMutation(false));
    };

    return (
        <GreyRowBox
            className={'flex-1 flex flex-col !items-stretch !p-0 min-h-0 overflow-hidden w-full max-w-full'}
            $hoverable={false}
            style={{
                alignItems: 'stretch',
                alignSelf: 'stretch',
                backgroundColor: themeColors.page.background,
                borderColor: themeColors.page.secondaryHover,
                display: 'flex',
                flex: '1 1 0%',
                flexDirection: 'column',
                height: '100%',
                maxWidth: '100%',
                minHeight: 0,
                minWidth: 0,
                width: '100%',
            }}
        >
            <div className={'flex flex-col gap-3 border-b px-4 py-3 lg:flex-row lg:items-center lg:justify-between'} style={viewerHeaderStyle}>
                <div className={'flex min-w-0 items-center'}>
                    <FaDatabase className={'mr-3 h-4 w-4 flex-shrink-0 text-blue-400'} />
                    <div className={'min-w-0'}>
                        <p className={'truncate text-sm font-medium text-neutral-100'}>{fileName}</p>
                        <p className={'text-xs text-neutral-500'}>
                            {database ? `${database.tables.length} table${database.tables.length === 1 ? '' : 's'} / SQLite database` : 'SQLite database'}
                        </p>
                    </div>
                </div>
                <div className={'flex w-full min-w-0 flex-col gap-2 sm:flex-row sm:items-center lg:ml-4 lg:w-auto lg:flex-shrink-0'}>
                    {database && (
                        <Button.Text className={'w-full justify-center sm:w-auto'} size={Button.Sizes.Small} disabled={readOnly} onClick={openCreateTableDialog}>
                            <FaPlus className={'mr-2 h-3 w-3'} />
                            Table
                        </Button.Text>
                    )}
                    <div className={'relative min-w-0 sm:min-w-[12rem] sm:flex-1 lg:w-64 lg:flex-none'}>
                        <FaSearch className={'pointer-events-none absolute left-3 top-1/2 h-3 w-3 -translate-y-1/2 text-neutral-500'} />
                        <Input
                            className={'!w-full !pl-8 !pr-3 !py-2 !text-xs'}
                            value={searchDraft}
                            onChange={(event) => setSearchDraft(event.currentTarget.value)}
                            placeholder={'Search rows'}
                            disabled={!activeTable}
                        />
                    </div>
                    <Select
                        className={'!w-full !px-3 !py-2 !text-xs sm:!w-24'}
                        value={perPage}
                        onChange={(event) => {
                            setPerPage(Number(event.currentTarget.value));
                            setPage(1);
                        }}
                    >
                        <option value={25}>25 rows</option>
                        <option value={50}>50 rows</option>
                        <option value={100}>100 rows</option>
                    </Select>
                </div>
            </div>

            {error && <div className={'border-b border-red-500/30 bg-red-500/10 px-4 py-2 text-xs text-red-300'}>{error}</div>}
            {error && (
                <div className={'border-b px-4 py-3'} style={viewerPanelStyle}>
                    <GreyRowBox className={'flex-col !items-stretch'} $hoverable={false}>
                        <div className={'flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between'}>
                            <div className={'min-w-0'}>
                                <p className={'text-sm font-medium text-neutral-100'}>Initialize SQLite database</p>
                                <p className={'mt-1 text-xs text-neutral-500'}>
                                    If this is a newly created empty database file, initialize it so Better Files can inspect tables and rows.
                                </p>
                            </div>
                            <div className={'flex flex-shrink-0 flex-wrap gap-2'}>
                                <Button.Text size={Button.Sizes.Small} disabled={loading || initializing} onClick={loadDatabase}>
                                    Retry
                                </Button.Text>
                                <Button size={Button.Sizes.Small} disabled={readOnly || loading || initializing} onClick={handleInitialize}>
                                    {initializing ? 'Initializing...' : 'Initialize'}
                                </Button>
                            </div>
                        </div>
                    </GreyRowBox>
                </div>
            )}

            <div className={'flex-1 min-h-0'} style={viewerBodyStyle}>
                {loading ? (
                    <div className={'flex h-full items-center justify-center'}>
                        <Spinner size={'large'} />
                    </div>
                ) : database ? (
                    <div className={'flex h-full min-h-0 flex-col lg:flex-row'}>
                        <aside
                            className={'flex min-h-0 w-full flex-1 flex-col border-b lg:h-full lg:w-64 lg:flex-none lg:border-b-0 lg:border-r'}
                            style={{ borderColor: themeColors.page.secondaryHover }}
                        >
                            <div className={'border-b px-3 py-2 text-[10px] uppercase tracking-wider text-neutral-500'} style={viewerHeaderStyle}>
                                Tables
                            </div>
                            <div className={'min-h-0 flex-1 overflow-y-auto overflow-x-hidden p-2'}>
                                {database.tables.length === 0 ? (
                                    <div className={'px-2 py-3'}>
                                        <p className={'text-xs text-neutral-500'}>No tables found.</p>
                                        <Button.Text className={'mt-3'} size={Button.Sizes.Small} disabled={readOnly} onClick={openCreateTableDialog}>
                                            Create Table
                                        </Button.Text>
                                    </div>
                                ) : database.tables.map((table) => (
                                    <button
                                        key={`${table.type}:${table.name}`}
                                        type={'button'}
                                        className={cx(
                                            'mb-1 flex w-full min-w-0 items-center rounded px-2 py-2 text-left text-xs transition-colors',
                                            activeTable === table.name
                                                ? 'bg-neutral-600 text-neutral-100'
                                                : 'text-neutral-300 hover:bg-neutral-700 hover:text-neutral-100'
                                        )}
                                        style={activeTable === table.name ? { backgroundColor: themeColors.page.secondaryHover } : undefined}
                                        onClick={() => {
                                            setActiveTable(table.name);
                                            setPage(1);
                                            setMutationError(null);
                                            setEditingCell(null);
                                            setRowEditorMode(null);
                                            setEditingRowId(null);
                                            setDeleteRowId(null);
                                        }}
                                    >
                                        <FaTable className={'mr-2 h-3 w-3 flex-shrink-0 text-neutral-500'} />
                                        <span className={'min-w-0 flex-1 truncate'} title={table.name}>{table.name}</span>
                                        <span className={'ml-2 flex-shrink-0 text-[10px] uppercase text-neutral-500'}>{tableLabel(table)}</span>
                                    </button>
                                ))}
                            </div>
                        </aside>

                        <section className={'flex min-h-0 min-w-0 flex-1 flex-col'}>
                            <div className={'flex flex-col gap-3 border-b border-neutral-700 px-4 py-3 lg:flex-row lg:items-center lg:justify-between'}>
                                <div className={'min-w-0'}>
                                    <p className={'truncate text-sm font-medium text-neutral-100'}>{activeTable || 'No table selected'}</p>
                                    <p className={'text-xs text-neutral-500'}>
                                        {activeSummary ? `${tableLabel(activeSummary)} / ${pagination?.total ?? 0} row${pagination?.total === 1 ? '' : 's'}` : 'Select a table to inspect rows'}
                                    </p>
                                </div>
                                {(pagination || tableData?.editable) && (
                                    <div className={'flex flex-wrap items-center gap-2'}>
                                        {tableData?.editable && !readOnly && (
                                            <Button size={Button.Sizes.Small} onClick={openInsertDialog}>
                                                <FaPlus className={'mr-2 h-3 w-3'} />
                                                Add Row
                                            </Button>
                                        )}
                                        {pagination && (
                                            <>
                                                <Button.Text size={Button.Sizes.Small} disabled={!canPrevious || tableLoading} onClick={() => setPage((value) => Math.max(1, value - 1))}>
                                                    Previous
                                                </Button.Text>
                                                <span className={'text-xs text-neutral-500'}>
                                                    Page {pagination.current_page} / {pagination.total_pages}
                                                </span>
                                                <Button.Text size={Button.Sizes.Small} disabled={!canNext || tableLoading} onClick={() => setPage((value) => value + 1)}>
                                                    Next
                                                </Button.Text>
                                            </>
                                        )}
                                    </div>
                                )}
                            </div>

                            {tableError && <div className={'border-b border-red-500/30 bg-red-500/10 px-4 py-2 text-xs text-red-300'}>{tableError}</div>}
                            {mutationError && <div className={'border-b border-red-500/30 bg-red-500/10 px-4 py-2 text-xs text-red-300'}>{mutationError}</div>}

                            {tableLoading ? (
                                <div className={'flex flex-1 items-center justify-center'}>
                                    <Spinner size={'large'} />
                                </div>
                            ) : tableData ? (
                                <>
                                    <div className={'border-b border-neutral-700 px-4 py-3'}>
                                        <div className={'flex flex-wrap gap-2'}>
                                            {tableData.columns.map((column) => (
                                                <span key={column.name} className={'inline-flex items-center rounded border border-neutral-600 px-2 py-1 text-[10px] text-neutral-400'}>
                                                    <span className={'font-mono text-neutral-200'}>{column.name}</span>
                                                    <span className={'ml-1 text-neutral-500'}>{column.type || 'value'}</span>
                                                    {column.primary_key && <span className={'ml-1 text-yellow-400'}>PK</span>}
                                                </span>
                                            ))}
                                            {tableData.indexes.map((index) => (
                                                <span key={index.name} className={'inline-flex items-center rounded border border-neutral-600 px-2 py-1 text-[10px] text-neutral-500'}>
                                                    {index.unique ? 'Unique index' : 'Index'}: {index.name}
                                                </span>
                                            ))}
                                        </div>
                                    </div>
                                    <div className={'min-h-0 flex-1 overflow-auto'}>
                                        {tableData.rows.length === 0 ? (
                                            <div className={'flex h-full items-center justify-center text-sm text-neutral-500'}>No rows found.</div>
                                        ) : (
                                            <table className={'min-w-[720px] table-auto border-separate border-spacing-0 text-left text-xs lg:min-w-full'}>
                                            <thead className={'sticky top-0 z-10 text-[10px] uppercase tracking-wider text-neutral-500'} style={viewerBodyStyle}>
                                                    <tr>
                                                        {tableData.editable && !readOnly && (
                                                            <th className={'w-32 border-b border-neutral-700 px-3 py-2 font-medium'}>
                                                                Row
                                                            </th>
                                                        )}
                                                        {tableData.columns.map((column) => (
                                                            <th key={column.name} className={'border-b border-neutral-700 px-3 py-2 font-medium'}>
                                                                {column.name}
                                                            </th>
                                                        ))}
                                                    </tr>
                                                </thead>
                                                <tbody>
                                                    {tableData.rows.map((row, rowIndex) => {
                                                        const rowId = typeof row.__betterfiles_rowid__ === 'number' ? row.__betterfiles_rowid__ : null;

                                                        return (
                                                            <tr key={`${tableData.table}:${pagination?.current_page || 1}:${rowId || rowIndex}`} className={'group hover:bg-neutral-700/60'}>
                                                                {tableData.editable && !readOnly && (
                                                                    <td className={'w-32 border-b border-neutral-700/70 px-3 py-2 align-top'}>
                                                                        <div className={'flex items-center gap-1'}>
                                                                            <span className={'mr-1 w-8 flex-shrink-0 font-mono text-[10px] text-neutral-500'}>
                                                                                {rowId || '-'}
                                                                            </span>
                                                                            <div className={'flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100'}>
                                                                                <Button.Text
                                                                                    type={'button'}
                                                                                    size={Button.Sizes.Small}
                                                                                    disabled={readOnly || !rowId}
                                                                                    className={'h-6 min-w-[1.5rem] px-1.5'}
                                                                                    title={'Edit row'}
                                                                                    aria-label={'Edit row'}
                                                                                    onClick={() => rowId && openEditRowDialog(row, rowId)}
                                                                                >
                                                                                    <FaEdit className={'h-3 w-3'} />
                                                                                </Button.Text>
                                                                                <Button.Text
                                                                                    type={'button'}
                                                                                    size={Button.Sizes.Small}
                                                                                    disabled={readOnly || !rowId}
                                                                                    className={'h-6 min-w-[1.5rem] px-1.5'}
                                                                                    title={'Duplicate row'}
                                                                                    aria-label={'Duplicate row'}
                                                                                    onClick={() => openDuplicateRowDialog(row)}
                                                                                >
                                                                                    <FaCopy className={'h-3 w-3'} />
                                                                                </Button.Text>
                                                                                <Button.Danger
                                                                                    type={'button'}
                                                                                    size={Button.Sizes.Small}
                                                                                    disabled={readOnly || !rowId}
                                                                                    className={'h-6 min-w-[1.5rem] px-1.5'}
                                                                                    title={'Delete row'}
                                                                                    aria-label={'Delete row'}
                                                                                    onClick={() => rowId && setDeleteRowId(rowId)}
                                                                                >
                                                                                    <FaTrash className={'h-3 w-3'} />
                                                                                </Button.Danger>
                                                                            </div>
                                                                        </div>
                                                                    </td>
                                                                )}
                                                                {tableData.columns.map((column) => {
                                                                    const value = row[column.name];
                                                                    const display = formatCell(value);
                                                                    const isEditing = !!editingCell && editingCell.rowId === rowId && editingCell.column === column.name;
                                                                    const canEditCell = !readOnly && tableData.editable && !!rowId && !column.primary_key;

                                                                    return (
                                                                        <td key={column.name} className={'max-w-md border-b border-neutral-700/70 px-3 py-2 align-top text-neutral-300'}>
                                                                            {isEditing ? (
                                                                                <div className={'min-w-[14rem]'}>
                                                                                    <Input
                                                                                        autoFocus
                                                                                        className={'!h-8 !w-full !min-w-[12rem] !py-1 !text-xs font-mono'}
                                                                                        value={editingCell.value}
                                                                                        disabled={readOnly || savingMutation}
                                                                                        onFocus={(event) => event.currentTarget.select()}
                                                                                        onBlur={(event) => {
                                                                                            if (event.currentTarget.dataset.cancelled === 'true') return;
                                                                                            handleSaveCell();
                                                                                        }}
                                                                                        onChange={(event) => setEditingCell({
                                                                                            ...editingCell,
                                                                                            value: event.currentTarget.value,
                                                                                        })}
                                                                                        onKeyDown={(event) => {
                                                                                            if (event.key === 'Enter') {
                                                                                                event.preventDefault();
                                                                                                event.currentTarget.blur();
                                                                                            }
                                                                                            if (event.key === 'Escape') {
                                                                                                event.preventDefault();
                                                                                                event.currentTarget.dataset.cancelled = 'true';
                                                                                                setEditingCell(null);
                                                                                            }
                                                                                        }}
                                                                                    />
                                                                                    <p className={'mt-1 text-[10px] text-neutral-500'}>Enter saves, Escape cancels.</p>
                                                                                </div>
                                                                            ) : (
                                                                                <button
                                                                                    type={'button'}
                                                                                    disabled={!canEditCell}
                                                                                    className={cx(
                                                                                        'block max-h-24 w-full overflow-hidden whitespace-pre-wrap break-words text-left font-mono',
                                                                                        canEditCell && 'rounded px-1 py-0.5 hover:bg-neutral-600 hover:text-neutral-100',
                                                                                        !canEditCell && 'cursor-default',
                                                                                        value === null && 'text-neutral-600'
                                                                                    )}
                                                                                    title={canEditCell ? `${display} - click to edit` : display}
                                                                                    onClick={() => rowId && canEditCell && openCellEditor(rowId, column.name, value)}
                                                                                >
                                                                                    {display}
                                                                                </button>
                                                                            )}
                                                                        </td>
                                                                    );
                                                                })}
                                                            </tr>
                                                        );
                                                    })}
                                                </tbody>
                                            </table>
                                        )}
                                    </div>
                                </>
                            ) : (
                                <div className={'flex flex-1 items-center justify-center text-sm text-neutral-500'}>
                                    Select a table to view its rows.
                                </div>
                            )}
                        </section>
                    </div>
                ) : (
                    <div className={'flex h-full items-center justify-center text-sm text-neutral-500'}>No database loaded.</div>
                )}
            </div>

            <Dialog
                open={showCreateTableDialog}
                onClose={() => !savingMutation && setShowCreateTableDialog(false)}
                title={'Create Table'}
                description={'Create a simple SQLite table. Names may contain letters, numbers, and underscores.'}
            >
                <div className={'mt-4 space-y-4'}>
                    <div className={'space-y-1'}>
                        <label className={'block text-xs font-medium uppercase tracking-wider text-neutral-500'}>
                            Table name
                        </label>
                        <Input
                            value={createTableName}
                            onChange={(event) => setCreateTableName(event.currentTarget.value)}
                            placeholder={'players'}
                            disabled={readOnly || savingMutation}
                        />
                    </div>
                    <GreyRowBox className={'flex-col !items-stretch !p-0'} $hoverable={false}>
                        <div className={'border-b border-neutral-700 px-3 py-2 text-[10px] uppercase tracking-wider text-neutral-500'}>
                            Columns
                        </div>
                        <div className={'space-y-2 p-3'}>
                            {createTableColumns.map((column, index) => (
                                <div key={index} className={'grid grid-cols-1 gap-2 sm:grid-cols-[1fr_11rem_auto]'}>
                                    <Input
                                        value={column.name}
                                        onChange={(event) => setCreateTableColumns((columns) => columns.map((item, itemIndex) => (
                                            itemIndex === index ? { ...item, name: event.currentTarget.value } : item
                                        )))}
                                        placeholder={'column_name'}
                                        disabled={readOnly || savingMutation}
                                    />
                                    <Select
                                        value={column.type}
                                        onChange={(event) => setCreateTableColumns((columns) => columns.map((item, itemIndex) => (
                                            itemIndex === index ? { ...item, type: event.currentTarget.value as DatabaseCreateColumn['type'] } : item
                                        )))}
                                        disabled={readOnly || savingMutation}
                                    >
                                        {databaseColumnTypes.map((type) => (
                                            <option key={type} value={type}>{type}</option>
                                        ))}
                                    </Select>
                                    <Button.Danger
                                        type={'button'}
                                        size={Button.Sizes.Small}
                                    disabled={readOnly || savingMutation || createTableColumns.length === 1}
                                        onClick={() => setCreateTableColumns((columns) => columns.filter((_, itemIndex) => itemIndex !== index))}
                                    >
                                        Remove
                                    </Button.Danger>
                                </div>
                            ))}
                            <Button.Text
                                type={'button'}
                                size={Button.Sizes.Small}
                                disabled={readOnly || savingMutation || createTableColumns.length >= 64}
                                onClick={() => setCreateTableColumns((columns) => [...columns, { name: '', type: 'TEXT' }])}
                            >
                                Add Column
                            </Button.Text>
                        </div>
                    </GreyRowBox>
                    {mutationError && <p className={'text-xs text-red-300'}>{mutationError}</p>}
                </div>
                <Dialog.Footer>
                    <Button.Text type={'button'} onClick={() => setShowCreateTableDialog(false)} disabled={savingMutation}>
                        Cancel
                    </Button.Text>
                    <Button type={'button'} onClick={handleCreateTable} disabled={readOnly || savingMutation}>
                        Create Table
                    </Button>
                </Dialog.Footer>
            </Dialog>

            <Dialog
                open={rowEditorMode !== null}
                onClose={() => !savingMutation && setRowEditorMode(null)}
                title={rowEditorMode === 'edit' ? 'Edit Row' : rowEditorMode === 'duplicate' ? 'Duplicate Row' : 'Add Row'}
                description={activeTable ? (
                    rowEditorMode === 'edit'
                        ? `Update row ${editingRowId} in ${activeTable}.`
                        : rowEditorMode === 'duplicate'
                            ? `Create a new row in ${activeTable} from the selected row values.`
                            : `Insert a new row into ${activeTable}. Leave fields empty to use database defaults.`
                ) : undefined}
            >
                <div className={'mt-4 max-h-[60vh] space-y-3 overflow-y-auto pr-1'}>
                    {editableColumns.length === 0 ? (
                        <GreyRowBox className={'flex-col !items-stretch'} $hoverable={false}>
                            <p className={'text-sm text-neutral-300'}>This table only exposes generated primary key columns.</p>
                            <p className={'mt-1 text-xs text-neutral-500'}>Adding a row will use SQLite default values.</p>
                        </GreyRowBox>
                    ) : editableColumns.map((column) => (
                        <div key={column.name} className={'space-y-1'}>
                            <label className={'block text-xs font-medium uppercase tracking-wider text-neutral-500'}>
                                {column.name}
                                {column.type && <span className={'ml-2 font-normal text-neutral-600'}>{column.type}</span>}
                            </label>
                            <Input
                                value={newRowValues[column.name] || ''}
                                onChange={(event) => setNewRowValues((values) => ({
                                    ...values,
                                    [column.name]: event.currentTarget.value,
                                }))}
                                disabled={readOnly || savingMutation}
                            />
                        </div>
                    ))}
                    {mutationError && <p className={'text-xs text-red-300'}>{mutationError}</p>}
                </div>
                <Dialog.Footer>
                    <Button.Text type={'button'} onClick={() => setRowEditorMode(null)} disabled={savingMutation}>
                        Cancel
                    </Button.Text>
                    <Button type={'button'} onClick={handleSaveRow} disabled={readOnly || savingMutation}>
                        {rowEditorMode === 'edit' ? 'Save Row' : rowEditorMode === 'duplicate' ? 'Duplicate Row' : 'Add Row'}
                    </Button>
                </Dialog.Footer>
            </Dialog>

            <Dialog
                open={deleteRowId !== null}
                onClose={() => !savingMutation && setDeleteRowId(null)}
                title={'Delete Row'}
                description={deleteRowId ? `Delete row ${deleteRowId} from ${activeTable}? This cannot be undone.` : undefined}
            >
                {mutationError && <p className={'mt-4 text-xs text-red-300'}>{mutationError}</p>}
                <Dialog.Footer>
                    <Button.Text type={'button'} onClick={() => setDeleteRowId(null)} disabled={savingMutation}>
                        Cancel
                    </Button.Text>
                    <Button.Danger type={'button'} onClick={handleDeleteRow} disabled={readOnly || savingMutation}>
                        Delete
                    </Button.Danger>
                </Dialog.Footer>
            </Dialog>
        </GreyRowBox>
    );
};

export default DatabaseViewer;
