import React, { useEffect, useMemo, useState } from 'react';
import tw from 'twin.macro';
import { Button } from '@/components/elements/button';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Input from '@/components/elements/Input';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faMagic, faTable } from '@fortawesome/free-solid-svg-icons';
import Dialog from '../Dialog';
import { applyDatabasePresets, DatabasePreset, getDatabasePresets } from '../api/databasePresets';
import { ServerContext } from '@/state/server';
import useFlash from '@/plugins/useFlash';
import { httpErrorToHuman } from '@/api/http';
import FlashMessageRender from '@/components/FlashMessageRender';

interface Props {
    open: boolean;
    databaseId: string;
    databaseName: string;
    onClose: () => void;
    onApplied?: () => void;
}

const FLASH_KEY = 'database:content:presets-modal';

const DatabasePresetsModal = ({ open, databaseId, databaseName, onClose, onApplied }: Props) => {
    const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
    const { clearFlashes, addError } = useFlash();

    const [loading, setLoading] = useState(false);
    const [submitting, setSubmitting] = useState(false);
    const [presets, setPresets] = useState<Record<string, DatabasePreset>>({});
    const [selected, setSelected] = useState<string[]>([]);

    useEffect(() => {
        if (!open) {
            setSelected([]);
            setPresets({});
            setLoading(false);
            setSubmitting(false);
            clearFlashes(FLASH_KEY);
            return;
        }

        clearFlashes(FLASH_KEY);
        setLoading(true);
        getDatabasePresets(uuid, databaseId)
            .then((response) => setPresets(response.presets || {}))
            .catch((error) => addError({ key: FLASH_KEY, message: httpErrorToHuman(error) }))
            .finally(() => setLoading(false));
    }, [open, uuid, databaseId]);

    const groupedPresets = useMemo(() => {
        return Object.entries(presets).reduce<Record<string, Array<[string, DatabasePreset]>>>((acc, [key, preset]) => {
            const group = preset.category || 'General';
            if (!acc[group]) {
                acc[group] = [];
            }

            acc[group].push([key, preset]);
            return acc;
        }, {});
    }, [presets]);

    const toggle = (key: string) => {
        setSelected((current) => (current.includes(key) ? current.filter((item) => item !== key) : [...current, key]));
    };

    const submit = async () => {
        if (!selected.length) {
            addError({ key: FLASH_KEY, message: 'Select at least one preset.' });
            return;
        }

        setSubmitting(true);
        clearFlashes(FLASH_KEY);

        try {
            await applyDatabasePresets(uuid, databaseId, { presets: selected });
            onApplied && onApplied();
            onClose();
        } catch (error) {
            addError({ key: FLASH_KEY, message: httpErrorToHuman(error) });
        } finally {
            setSubmitting(false);
        }
    };

    return (
        <Dialog
            open={open}
            onClose={onClose}
            preventExternalClose={loading || submitting}
            title={'Database Presets'}
            description={`Quick setup with common database structures for ${databaseName}`}
        >
            <div css={tw`mt-6`}>
                <FlashMessageRender byKey={FLASH_KEY} css={tw`mb-4`} />

                {loading ? (
                    <p css={tw`text-sm text-neutral-300`}>Loading presets...</p>
                ) : Object.keys(groupedPresets).length < 1 ? (
                    <p css={tw`text-sm text-neutral-300`}>No presets available.</p>
                ) : (
                    <div css={tw`space-y-6 max-h-[560px] overflow-y-auto pr-1`}>
                        {Object.entries(groupedPresets).map(([category, items]) => (
                            <div key={category}>
                                <h3 css={tw`text-lg font-semibold text-neutral-100 mb-3`}>{category}</h3>
                                <div css={tw`grid grid-cols-1 md:grid-cols-2 gap-3`}>
                                    {items.map(([key, preset]) => {
                                        const checked = selected.includes(key);
                                        const tableCount = Object.keys(preset.tables || {}).length;

                                        return (
                                            <button
                                                key={key}
                                                type={'button'}
                                                onClick={() => toggle(key)}
                                                css={tw`w-full text-left`}
                                            >
                                                <GreyRowBox
                                                    $hoverable={false}
                                                    css={[
                                                        tw`block p-4 border transition-colors`,
                                                        checked
                                                            ? tw`border-primary-400 bg-neutral-500`
                                                            : tw`border-neutral-500`,
                                                    ]}
                                                >
                                                    <div css={tw`flex items-start justify-between gap-3`}>
                                                        <div css={tw`flex items-start gap-3`}>
                                                            <div
                                                                css={[
                                                                    tw`w-8 h-8 rounded flex items-center justify-center border`,
                                                                    checked
                                                                        ? tw`bg-primary-500/20 border-primary-400 text-primary-200`
                                                                        : tw`bg-neutral-600 border-neutral-500 text-neutral-300`,
                                                                ]}
                                                            >
                                                                <FontAwesomeIcon icon={faTable} fixedWidth />
                                                            </div>
                                                            <div css={tw`flex-1`}>
                                                                <p css={tw`text-base text-neutral-100 font-semibold`}>
                                                                    {preset.name}
                                                                </p>
                                                                <p css={tw`text-sm text-neutral-300 mt-1`}>
                                                                    {preset.description}
                                                                </p>
                                                                <p css={tw`text-xs text-neutral-400 mt-2`}>
                                                                    {tableCount} {tableCount === 1 ? 'table' : 'tables'}
                                                                </p>
                                                            </div>
                                                        </div>
                                                        <Input
                                                            type={'checkbox'}
                                                            checked={checked}
                                                            readOnly
                                                            css={tw`mt-1`}
                                                        />
                                                    </div>
                                                </GreyRowBox>
                                            </button>
                                        );
                                    })}
                                </div>
                            </div>
                        ))}
                    </div>
                )}
            </div>

            <Dialog.Footer>
                <div css={tw`w-full flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3`}>
                    <p css={tw`text-xs text-neutral-400 flex items-center`}>
                        <FontAwesomeIcon icon={faMagic} fixedWidth />
                        <span css={tw`ml-2`}>{selected.length} preset(s) selected</span>
                    </p>
                    <div css={tw`flex items-center gap-2 ml-auto`}>
                        <Button
                            type={'button'}
                            variant={Button.Variants.Secondary}
                            disabled={loading || submitting}
                            onClick={onClose}
                        >
                            Cancel
                        </Button>
                        <Button
                            type={'button'}
                            disabled={loading || submitting || selected.length < 1}
                            onClick={submit}
                        >
                            Apply Presets
                        </Button>
                    </div>
                </div>
            </Dialog.Footer>
        </Dialog>
    );
};

export default DatabasePresetsModal;
