import React, { useEffect, useMemo, useState } from 'react';
import { Dialog } from '@/components/elements/dialog';
import { Button } from '@/components/elements/button';
import Label from '@/components/elements/Label';
import FlashMessageRender from '@/components/FlashMessageRender';
import GreyRowBox from '@/components/elements/GreyRowBox';
import tw from 'twin.macro';
import { ServerContext } from '@/state/server';
import useFlash from '@/plugins/useFlash';
import { httpErrorToHuman } from '@/api/http';
import analyzeDatabaseHealth, { DatabaseHealthAnalysis } from '../api/analyzeDatabaseHealth';
import analyzeIndexes, { IndexAnalysisResult, IndexRecommendation } from '../api/analyzeIndexes';

interface Props {
    databaseId: string;
    databaseName: string;
    visible: boolean;
    onDismissed: () => void;
}

const FLASH_KEY = 'database:health';

const DatabaseHealthModal = ({ databaseId, databaseName, visible, onDismissed }: Props) => {
    const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
    const { clearFlashes, addError } = useFlash();

    const [loading, setLoading] = useState(false);
    const [health, setHealth] = useState<DatabaseHealthAnalysis | null>(null);
    const [indexAnalysis, setIndexAnalysis] = useState<IndexAnalysisResult | null>(null);

    const fetchAnalysis = async (forceRefresh = false) => {
        clearFlashes(FLASH_KEY);
        setLoading(true);

        try {
            const healthResult = await analyzeDatabaseHealth(uuid, databaseId, forceRefresh);
            setHealth(healthResult);
        } catch (error) {
            setHealth(null);
            addError({ key: FLASH_KEY, message: httpErrorToHuman(error) });
        }

        try {
            const indexResult = await analyzeIndexes(uuid, databaseId, forceRefresh);
            setIndexAnalysis(indexResult);
        } catch (error) {
            setIndexAnalysis(null);
            addError({ key: FLASH_KEY, message: httpErrorToHuman(error) });
        }

        setLoading(false);
    };

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

        fetchAnalysis(false);
    }, [visible]);

    const dismiss = () => {
        clearFlashes(FLASH_KEY);
        onDismissed();
    };

    const healthLabel = health?.overall_health?.toUpperCase() || 'UNKNOWN';

    const topIndexRecommendations = useMemo(() => {
        if (!indexAnalysis?.recommendations) return [];

        const flattened = Object.values(indexAnalysis.recommendations).reduce<IndexRecommendation[]>(
            (carry, recommendations) => carry.concat(recommendations),
            []
        );
        return flattened.slice(0, 5);
    }, [indexAnalysis]);

    return (
        <Dialog
            open={visible}
            onClose={dismiss}
            preventExternalClose={loading}
            title={'Database health'}
            description={`Health and index analysis for ${databaseName}.`}
        >
            <div className={'mt-6 space-y-4'}>
                <FlashMessageRender byKey={FLASH_KEY} css={tw`mb-2`} />

                <GreyRowBox $hoverable={false} css={tw`block p-4`}>
                    <div css={tw`grid grid-cols-2 sm:grid-cols-4 gap-3`}>
                        <div>
                            <Label css={tw`mb-1`}>Health score</Label>
                            <p css={tw`text-lg text-neutral-100`}>{health?.health_score ?? '-'}</p>
                        </div>
                        <div>
                            <Label css={tw`mb-1`}>Overall</Label>
                            <p css={tw`text-lg text-neutral-100`}>{healthLabel}</p>
                        </div>
                        <div>
                            <Label css={tw`mb-1`}>Performance score</Label>
                            <p css={tw`text-lg text-neutral-100`}>{indexAnalysis?.summary?.performance_score ?? '-'}</p>
                        </div>
                        <div>
                            <Label css={tw`mb-1`}>Critical issues</Label>
                            <p css={tw`text-lg text-neutral-100`}>
                                {indexAnalysis?.performance_impact?.critical_issues ?? '-'}
                            </p>
                        </div>
                    </div>
                </GreyRowBox>

                <div css={tw`grid grid-cols-2 sm:grid-cols-4 gap-2`}>
                    <GreyRowBox $hoverable={false} css={tw`block p-3`}>
                        <p css={tw`text-xs text-neutral-400`}>Tables</p>
                        <p css={tw`text-neutral-100`}>{health?.metrics?.tables?.total_tables ?? '-'}</p>
                    </GreyRowBox>
                    <GreyRowBox $hoverable={false} css={tw`block p-3`}>
                        <p css={tw`text-xs text-neutral-400`}>Rows</p>
                        <p css={tw`text-neutral-100`}>{health?.metrics?.tables?.total_rows ?? '-'}</p>
                    </GreyRowBox>
                    <GreyRowBox $hoverable={false} css={tw`block p-3`}>
                        <p css={tw`text-xs text-neutral-400`}>DB size (MB)</p>
                        <p css={tw`text-neutral-100`}>{health?.metrics?.size?.total_size_mb ?? '-'}</p>
                    </GreyRowBox>
                    <GreyRowBox $hoverable={false} css={tw`block p-3`}>
                        <p css={tw`text-xs text-neutral-400`}>Indexes</p>
                        <p css={tw`text-neutral-100`}>{indexAnalysis?.summary?.total_indexes ?? '-'}</p>
                    </GreyRowBox>
                </div>

                <div>
                    <Label css={tw`mb-2`}>Health alerts</Label>
                    <div css={tw`max-h-44 overflow-y-auto border border-neutral-600 rounded p-2`}>
                        {!health?.alerts?.length ? (
                            <p css={tw`text-sm text-neutral-400 px-2 py-1`}>No health alerts reported.</p>
                        ) : (
                            health.alerts.map((alert, index) => (
                                <GreyRowBox
                                    key={`${alert.type}-${index}`}
                                    $hoverable={false}
                                    css={tw`block p-3 mb-2 last:mb-0`}
                                >
                                    <p css={tw`text-sm text-neutral-100`}>
                                        {alert.title} <span css={tw`text-xs text-neutral-400`}>({alert.severity})</span>
                                    </p>
                                    <p css={tw`text-xs text-neutral-400 mt-1`}>{alert.description}</p>
                                    <p css={tw`text-xs text-neutral-300 mt-1`}>{alert.recommendation}</p>
                                </GreyRowBox>
                            ))
                        )}
                    </div>
                </div>

                <div>
                    <Label css={tw`mb-2`}>Index recommendations</Label>
                    <div css={tw`max-h-44 overflow-y-auto border border-neutral-600 rounded p-2`}>
                        {!topIndexRecommendations.length ? (
                            <p css={tw`text-sm text-neutral-400 px-2 py-1`}>No index recommendations reported.</p>
                        ) : (
                            topIndexRecommendations.map((item: IndexRecommendation, index: number) => (
                                <GreyRowBox
                                    key={`${item.type}-${index}`}
                                    $hoverable={false}
                                    css={tw`block p-3 mb-2 last:mb-0`}
                                >
                                    <p css={tw`text-sm text-neutral-100`}>
                                        {item.title} <span css={tw`text-xs text-neutral-400`}>({item.priority})</span>
                                    </p>
                                    <p css={tw`text-xs text-neutral-400 mt-1`}>{item.description}</p>
                                    <p css={tw`text-xs text-neutral-300 mt-1`}>{item.recommendation}</p>
                                </GreyRowBox>
                            ))
                        )}
                    </div>
                </div>

                <GreyRowBox $hoverable={false} css={tw`block p-3`}>
                    <p css={tw`text-xs text-neutral-400`}>Index summary</p>
                    <p css={tw`text-sm text-neutral-200 mt-1`}>
                        Missing: {indexAnalysis?.summary?.missing_indexes ?? '-'} | Unused:{' '}
                        {indexAnalysis?.summary?.unused_indexes ?? '-'} | Redundant:{' '}
                        {indexAnalysis?.summary?.redundant_indexes ?? '-'}
                    </p>
                </GreyRowBox>
            </div>

            <Dialog.Footer>
                <Button type={'button'} variant={Button.Variants.Secondary} disabled={loading} onClick={dismiss}>
                    Close
                </Button>
                <Button
                    type={'button'}
                    variant={Button.Variants.Secondary}
                    disabled={loading}
                    onClick={() => fetchAnalysis(true)}
                >
                    {loading ? 'Refreshing...' : 'Refresh Analysis'}
                </Button>
            </Dialog.Footer>
        </Dialog>
    );
};

export default DatabaseHealthModal;
