import { useEffect, useMemo, useState } from "react";
import { listen } from "@tauri-apps/api/event";
import { WebviewWindow } from "@tauri-apps/api/webviewWindow";
import {
    AreaChart,
    BarChart3,
    ChevronDown,
    Cog,
    Columns2,
    Copy,
    Grid2X2,
    GripVertical,
    LineChart,
    Maximize2,
    PanelTop,
    Play,
    Plus,
    Rows2,
    Search,
    Trash2,
    X,
} from "lucide-react";

import { ChartConfigModal } from "../../chartworkspace/components/ChartConfigModal";
import { openChartWindow } from "../../chartworkspace/utils/openChartWindow";

import {
    WorkspaceChart,
    type WorkspaceChartConfig,
    type WorkspaceChartInterval,
    type WorkspaceChartMode,
    type WorkspaceChartTimeRange,
} from "../../../components/charts/WorkspaceChart";

import type { ChartVariable } from "../../telemetry/types/telemetryCatalog";
import { useMeteoChartCatalog } from "../hooks/useMeteoChartCatalog";

import {
    useChartWorkspacePersistence,
    type ChartLayoutMode,
    type PersistedChartWorkspaceItem,
} from "../../chartworkspace/hooks/useChartWorkspacePersistence";

type MeteoChartsPageProps = {
    theme: "dark" | "light";
};

type HistorianPoint = {
    timestamp: string;
    numericValue: number | null;
    value?: number | string;
    v?: number | string;
    total?: number | string;
};

type ChartWorkspaceItem = PersistedChartWorkspaceItem & {
    hidden?: boolean;
    collapsed?: boolean;
    id: string;
    title: string;
    subtitle: string;
    mode: WorkspaceChartMode;
    selectedSensorKeys: string[];
    hiddenSensorKeys?: string[];
    timeRange: WorkspaceChartTimeRange;
    interval: WorkspaceChartInterval;
    detached?: boolean;
    windowX?: number;
    windowY?: number;
    windowWidth?: number;
    windowHeight?: number;
    windowZIndex?: number;
};

const BACKEND_URL = "http://localhost:18450";
const RADIUS = "rounded-[6px]";
const MAX_CHARTS = 10;
const MAX_VARIABLES_PER_CHART = 6;

const INITIAL_CHARTS: ChartWorkspaceItem[] = [];

export function MeteoChartsPage({
    theme,
}: MeteoChartsPageProps) {

    const isDark = theme === "dark";

    const {
        chartableVariables,
        connected,
    } = useMeteoChartCatalog();

    const [layoutMode, setLayoutMode] = useState<ChartLayoutMode>("twoColumns");
    const [charts, setCharts] = useState<ChartWorkspaceItem[]>(INITIAL_CHARTS);
    const [configChartId, setConfigChartId] = useState<string | null>(null);
    const [savedSearch, setSavedSearch] = useState("");
    const [savedOpen, setSavedOpen] = useState(false);
    const [movingChartId, setMovingChartId] = useState<string | null>(null);
    const [newChartOpen, setNewChartOpen] = useState(false);
    const [placingChartId, setPlacingChartId] = useState<string | null>(null);

    const changeLayoutMode = (nextLayoutMode: ChartLayoutMode) => {
        const nextVisibleCount = getVisibleSlotCount(nextLayoutMode);

        setCharts((current) => {
            let openSeen = 0;

            return current.map((chart) => {
                if (chart.hidden) return chart;

                openSeen += 1;

                return {
                    ...chart,
                    collapsed: openSeen > nextVisibleCount,
                };
            });
        });

        setLayoutMode(nextLayoutMode);
        setPlacingChartId(null);
        setMovingChartId(null);
    };

    const workspacePersistence = useChartWorkspacePersistence({
        scope: "METEO",
        layoutMode,
        charts,
        onLoaded: (workspace) => {
            setLayoutMode(workspace.layoutMode);
            setCharts(workspace.charts as ChartWorkspaceItem[]);
        },
    });

    const canAddMoreCharts = charts.length < MAX_CHARTS;

    const visibleCharts = useMemo(() => {
        const openCharts = charts.filter(
            (chart) => !chart.hidden && !chart.collapsed && !chart.detached,
        );

        if (layoutMode === "single") return openCharts.slice(0, 1);
        if (layoutMode === "twoColumns") return openCharts.slice(0, 2);
        if (layoutMode === "twoRows") return openCharts.slice(0, 2);
        return openCharts.slice(0, 4);
    }, [charts, layoutMode]);

    const savedCharts = useMemo(
        () =>
            charts.filter((chart) =>
                chart.title.toLowerCase().includes(savedSearch.toLowerCase()),
            ),
        [charts, savedSearch],
    );

    const configChart = charts.find((chart) => chart.id === configChartId) ?? null;

    const swapCharts = (sourceId: string, targetId: string) => {
        if (sourceId === targetId) {
            setMovingChartId(null);
            return;
        }

        setCharts((current) => {
            const sourceIndex = current.findIndex((chart) => chart.id === sourceId);
            const targetIndex = current.findIndex((chart) => chart.id === targetId);

            if (sourceIndex === -1 || targetIndex === -1) return current;

            const next = [...current];
            [next[sourceIndex], next[targetIndex]] = [
                next[targetIndex],
                next[sourceIndex],
            ];

            return next;
        });

        setMovingChartId(null);
    };

    const addChart = ({
        title,
        mode,
        selectedSensorKeys,
    }: {
        title: string;
        mode: WorkspaceChartMode;
        selectedSensorKeys: string[];
    }) => {
        if (!canAddMoreCharts) return;

        const newChartId = `chart-${Date.now()}`;

        setCharts((current) => {
            const visibleSlotCount = getVisibleSlotCount(layoutMode);
            const visibleOpenCount = current.filter(
                (chart) => !chart.hidden && !chart.collapsed && !chart.detached,
            ).length;

            const shouldAskPlacement = visibleOpenCount >= visibleSlotCount;

            const newChart: ChartWorkspaceItem = {
                id: newChartId,
                title,
                subtitle: "Gráfico personalizado de meteorologia.",
                mode,
                selectedSensorKeys,
                timeRange: "24h",
                interval: "5m",
                hidden: false,
                collapsed: shouldAskPlacement,
            };

            if (shouldAskPlacement) setPlacingChartId(newChartId);

            return [...current, newChart];
        });

        setNewChartOpen(false);
    };

    const duplicateChart = (chartId: string) => {
        if (!canAddMoreCharts) return;

        const chart = charts.find((item) => item.id === chartId);
        if (!chart) return;

        const copy: ChartWorkspaceItem = {
            ...chart,
            id: `chart-${Date.now()}`,
            title: `${chart.title} cópia`,
        };

        setCharts((current) => {
            const next = [...current, copy];

            if (next.length >= 3) {
                setLayoutMode("fourGrid");
            } else if (next.length === 2) {
                setLayoutMode("twoColumns");
            }

            return next;
        });
    };

    const setChartMode = (chartId: string, mode: WorkspaceChartMode) => {
        setCharts((current) =>
            current.map((chart) =>
                chart.id === chartId ? { ...chart, mode } : chart,
            ),
        );
    };

    const toggleVariable = (chartId: string, key: string) => {
        setCharts((current) =>
            current.map((chart) => {
                if (chart.id !== chartId) return chart;

                const hiddenSensorKeys = chart.hiddenSensorKeys ?? [];
                const isHidden = hiddenSensorKeys.includes(key);

                return {
                    ...chart,
                    hiddenSensorKeys: isHidden
                        ? hiddenSensorKeys.filter((item) => item !== key)
                        : [...hiddenSensorKeys, key],
                };
            }),
        );
    };

    const loadSavedChart = (chartId: string) => {
        setCharts((current) => {
            const selected = current.find((chart) => chart.id === chartId);
            if (!selected) return current;

            const remaining = current.filter((chart) => chart.id !== chartId);

            return [
                { ...selected, hidden: false, collapsed: false },
                ...remaining,
            ];
        });

        setSavedOpen(false);
        setPlacingChartId(null);
    };

    const closeDetachedChartWindow = async (chartId: string) => {
        const label = `meteocharts-${chartId}`;
        const existing = await WebviewWindow.getByLabel(label);

        if (!existing) return;

        try {
            await existing.destroy();
        } catch (error) {
            console.error(`Failed to destroy detached chart window: ${label}`, error);
        }
    };

    const closeChart = async (chartId: string) => {
        await closeDetachedChartWindow(chartId);

        setCharts((current) =>
            current.map((chart) =>
                chart.id === chartId
                    ? {
                        ...chart,
                        detached: false,
                        hidden: true,
                        collapsed: false,
                    }
                    : chart,
            ),
        );

        if (configChartId === chartId) setConfigChartId(null);
        if (movingChartId === chartId) setMovingChartId(null);
        if (placingChartId === chartId) setPlacingChartId(null);
    };

    const deleteChart = async (chartId: string) => {
        await closeDetachedChartWindow(chartId);

        setCharts((current) => current.filter((chart) => chart.id !== chartId));

        if (configChartId === chartId) setConfigChartId(null);
        if (movingChartId === chartId) setMovingChartId(null);
        if (placingChartId === chartId) setPlacingChartId(null);
    };

    const placeChartHere = (targetChartId: string) => {
        if (!placingChartId || placingChartId === targetChartId) return;

        setCharts((current) => {
            const sourceIndex = current.findIndex((chart) => chart.id === placingChartId);
            const targetIndex = current.findIndex((chart) => chart.id === targetChartId);

            if (sourceIndex === -1 || targetIndex === -1) return current;

            const next = [...current];
            const source = next[sourceIndex];
            const target = next[targetIndex];

            next[targetIndex] = {
                ...source,
                hidden: false,
                collapsed: false,
            };

            next[sourceIndex] = {
                ...target,
                hidden: false,
                collapsed: true,
            };

            return next;
        });

        setPlacingChartId(null);
    };

    const openSavedChart = (chartId: string) => {
        const chart = charts.find((item) => item.id === chartId);
        if (!chart) return;

        const isActuallyOpen = !chart.hidden && !chart.collapsed && !chart.detached;
        if (isActuallyOpen) return;

        const visibleSlotCount = getVisibleSlotCount(layoutMode);
        const visibleOpenCount = charts.filter(
            (item) => !item.hidden && !item.collapsed && !item.detached,
        ).length;

        if (visibleOpenCount === 0 || visibleOpenCount < visibleSlotCount) {
            loadSavedChart(chartId);
            return;
        }

        setPlacingChartId(chartId);
        setSavedOpen(false);
    };

    const detachChart = (chartId: string) => {
        setCharts((current) =>
            current.map((chart) =>
                chart.id === chartId
                    ? {
                        ...chart,
                        detached: true,
                        hidden: false,
                        collapsed: false,
                    }
                    : chart,
            ),
        );

        window.setTimeout(() => {
            const chart = charts.find((item) => item.id === chartId);

            openChartWindow(
                chartId,
                theme,
                chart?.title ?? "Meteo Chart",
                "METEO",
                "meteocharts",
            );
        }, 100);
    };

    const attachChart = async (chartId: string) => {
        setCharts((current) =>
            current.map((chart) =>
                chart.id === chartId
                    ? {
                        ...chart,
                        detached: false,
                        hidden: false,
                        collapsed: false,
                    }
                    : chart,
            ),
        );

        await closeDetachedChartWindow(chartId);
    };

    const moveDetachedChart = (chartId: string, x: number, y: number) => {
        setCharts((current) =>
            current.map((chart) =>
                chart.id === chartId ? { ...chart, windowX: x, windowY: y } : chart,
            ),
        );
    };

    useEffect(() => {
        const unlistenAttachPromise = listen<{
            chartId: string;
            chart: ChartWorkspaceItem | null;
        }>("meteocharts://attach-chart", (event) => {
            const chartId = event.payload.chartId;
            const updatedChart = event.payload.chart;

            setCharts((current) => {
                const visibleSlotCount = getVisibleSlotCount(layoutMode);

                const visibleOpenCount = current.filter(
                    (chart) =>
                        !chart.hidden &&
                        !chart.collapsed &&
                        !chart.detached &&
                        chart.id !== chartId,
                ).length;

                const shouldAskPlacement = visibleOpenCount >= visibleSlotCount;

                if (shouldAskPlacement) setPlacingChartId(chartId);

                return current.map((chart) =>
                    chart.id === chartId
                        ? {
                            ...chart,
                            ...(updatedChart ?? {}),
                            detached: false,
                            hidden: false,
                            collapsed: shouldAskPlacement,
                        }
                        : chart,
                );
            });
        });

        const unlistenHidePromise = listen<{
            chartId?: string;
            chart?: ChartWorkspaceItem | null;
        }>("meteocharts://hide-chart", (event) => {
            const chartId = event.payload.chartId ?? event.payload.chart?.id;
            if (!chartId) return;

            setCharts((current) =>
                current.map((chart) =>
                    chart.id === chartId
                        ? {
                            ...chart,
                            ...(event.payload.chart ?? {}),
                            detached: false,
                            hidden: true,
                            collapsed: false,
                        }
                        : chart,
                ),
            );

            setPlacingChartId((current) => (current === chartId ? null : current));
        });

        const unlistenUpdatePromise = listen<{
            chartId: string;
            patch: Partial<ChartWorkspaceItem>;
        }>("meteocharts://update-chart", (event) => {
            const { chartId, patch } = event.payload;

            setCharts((current) =>
                current.map((chart) =>
                    chart.id === chartId
                        ? {
                            ...chart,
                            ...patch,
                        }
                        : chart,
                ),
            );
        });

        const unlistenReplacePromise = listen<{ chart: ChartWorkspaceItem }>(
            "meteocharts://replace-chart",
            (event) => {
                const updatedChart = event.payload.chart;

                setCharts((current) =>
                    current.map((chart) =>
                        chart.id === updatedChart.id
                            ? { ...chart, ...updatedChart }
                            : chart,
                    ),
                );
            },
        );

        return () => {
            void unlistenAttachPromise.then((unlisten) => unlisten());
            void unlistenHidePromise.then((unlisten) => unlisten());
            void unlistenUpdatePromise.then((unlisten) => unlisten());
            void unlistenReplacePromise.then((unlisten) => unlisten());
        };
    }, [layoutMode]);

    return (
        <div className="flex h-[calc(100vh-88px)] min-h-0 flex-col gap-3 overflow-hidden pb-2">
            <div
                className={
                    isDark
                        ? `${RADIUS} relative flex flex-wrap items-center gap-3 border border-[#263247] bg-[#0E1726] p-2`
                        : `${RADIUS} relative flex flex-wrap items-center gap-3 border border-[#D7DEE8] bg-white p-2`
                }
            >
                <div className="flex items-center gap-2">
                    <LayoutButton
                        theme={theme}
                        active={layoutMode === "single"}
                        icon={<PanelTop className="h-4 w-4" />}
                        title="1 gráfico"
                        onClick={() => changeLayoutMode("single")}
                    />

                    <LayoutButton
                        theme={theme}
                        active={layoutMode === "twoColumns"}
                        icon={<Columns2 className="h-4 w-4" />}
                        title="2 lado a lado"
                        onClick={() => changeLayoutMode("twoColumns")}
                    />

                    <LayoutButton
                        theme={theme}
                        active={layoutMode === "twoRows"}
                        icon={<Rows2 className="h-4 w-4" />}
                        title="2 vertical"
                        onClick={() => changeLayoutMode("twoRows")}
                    />

                    <LayoutButton
                        theme={theme}
                        active={layoutMode === "fourGrid"}
                        icon={<Grid2X2 className="h-4 w-4" />}
                        title="4 gráficos"
                        onClick={() => changeLayoutMode("fourGrid")}
                    />
                </div>

                <div className="ml-auto flex items-center gap-4">
                    <div
                        className={
                            isDark
                                ? "text-xs font-bold text-[#7F8CA3]"
                                : "text-xs font-bold text-slate-500"
                        }
                    >
                        {!workspacePersistence.loaded
                            ? "A carregar..."
                            : workspacePersistence.saving
                                ? "A guardar..."
                                : workspacePersistence.error
                                    ? workspacePersistence.error
                                    : "Workspace guardado"}
                    </div>

                    <div className="relative">
                        <button
                            type="button"
                            onClick={() => setSavedOpen((value) => !value)}
                            className={
                                isDark
                                    ? `flex h-10 items-center gap-3 ${RADIUS} border border-[#263247] bg-[#111A2B] px-4 text-sm font-bold text-white transition hover:border-[#36506D]`
                                    : `flex h-10 items-center gap-3 ${RADIUS} border border-[#D7DEE8] bg-white px-4 text-sm font-bold text-[#0F172A] transition hover:bg-[#F8FAFC]`
                            }
                        >
                            <Search className="h-4 w-4" />
                            Gráficos Guardados
                            <ChevronDown
                                className={
                                    savedOpen
                                        ? "h-4 w-4 rotate-180 text-[#7F8CA3] transition"
                                        : "h-4 w-4 text-[#7F8CA3] transition"
                                }
                            />
                        </button>

                        {savedOpen && (
                            <SavedChartsDropdown
                                theme={theme}
                                charts={savedCharts}
                                search={savedSearch}
                                onSearchChange={setSavedSearch}
                                onClose={() => {
                                    setSavedOpen(false);
                                    setPlacingChartId(null);
                                }}
                                onStartPlacement={openSavedChart}
                                onDelete={deleteChart}
                            />
                        )}
                    </div>

                    <button
                        type="button"
                        disabled={!canAddMoreCharts}
                        onClick={() => setNewChartOpen(true)}
                        className={
                            canAddMoreCharts
                                ? `flex h-10 items-center gap-3 ${RADIUS} bg-[#18B8A6] px-5 text-sm font-black text-white transition hover:bg-[#21C7B5]`
                                : `flex h-10 cursor-not-allowed items-center gap-3 ${RADIUS} bg-[#18B8A6]/40 px-5 text-sm font-black text-white`
                        }
                    >
                        <Plus className="h-5 w-5" />
                        Novo Gráfico
                    </button>
                </div>
            </div>

            {visibleCharts.length === 0 ? (
                <EmptyWorkspace
                    theme={theme}
                    canAddMoreCharts={canAddMoreCharts}
                    onAddChart={() => {
                        if (canAddMoreCharts) setNewChartOpen(true);
                    }}
                    onOpenSaved={() => setSavedOpen(true)}
                />
            ) : (
                <section className={layoutGridClass(layoutMode)}>
                    {visibleCharts.map((chartItem) => (
                        <WorkspaceChartContainer
                            key={chartItem.id}
                            theme={theme}
                            chartItem={chartItem}
                            chartableVariables={chartableVariables}
                            connected={connected}
                            movingChartId={movingChartId}
                            setMovingChartId={setMovingChartId}
                            swapCharts={swapCharts}
                            duplicateChart={duplicateChart}
                            closeChart={closeChart}
                            setConfigChartId={setConfigChartId}
                            setChartMode={setChartMode}
                            toggleVariable={toggleVariable}
                            setCharts={setCharts}
                            placingChartId={placingChartId}
                            placeChartHere={placeChartHere}
                            detachChart={detachChart}
                            attachChart={attachChart}
                            moveDetachedChart={moveDetachedChart}
                        />
                    ))}

                    {placingChartId && visibleCharts.length < getVisibleSlotCount(layoutMode) && (
                        <button
                            type="button"
                            onClick={() => {
                                if (!placingChartId) return;

                                setCharts((current) => {
                                    const source = current.find(
                                        (chart) => chart.id === placingChartId,
                                    );
                                    if (!source || (!source.hidden && !source.collapsed)) {
                                        return current;
                                    }

                                    const withoutSource = current.filter(
                                        (chart) => chart.id !== placingChartId,
                                    );

                                    return [
                                        ...visibleCharts,
                                        {
                                            ...source,
                                            hidden: false,
                                            collapsed: false,
                                        },
                                        ...withoutSource.filter(
                                            (chart) =>
                                                !visibleCharts.some(
                                                    (visible) => visible.id === chart.id,
                                                ),
                                        ),
                                    ];
                                });

                                if (visibleCharts.length + 1 >= 3) {
                                    setLayoutMode("fourGrid");
                                }

                                setPlacingChartId(null);
                            }}
                            className={
                                isDark
                                    ? `${RADIUS} flex min-h-0 items-center justify-center border-2 border-dashed border-[#4FD1C5] bg-[#07101B]/60 text-sm font-black text-[#4FD1C5]`
                                    : `${RADIUS} flex min-h-0 items-center justify-center border-2 border-dashed border-[#0F766E] bg-[#ECFDF5] text-sm font-black text-[#0F766E]`
                            }
                        >
                            Colocar em novo espaço
                        </button>
                    )}
                </section>
            )}

            {newChartOpen && (
                <NewChartModal
                    theme={theme}
                    variables={chartableVariables}
                    chartNumber={charts.length + 1}
                    onClose={() => setNewChartOpen(false)}
                    onCreate={addChart}
                />
            )}

            {configChart && (
                <ChartConfigModal
                    theme={theme}
                    chart={configChart}
                    variables={chartableVariables}
                    onClose={() => setConfigChartId(null)}
                    onSave={(updatedChart) => {
                        setCharts((current) =>
                            current.map((chart) =>
                                chart.id === updatedChart.id
                                    ? { ...chart, ...updatedChart }
                                    : chart,
                            ),
                        );

                        setConfigChartId(null);
                    }}
                />
            )}
        </div>
    );
}

function WorkspaceChartContainer({
    theme,
    chartItem,
    chartableVariables,
    connected,
    movingChartId,
    setMovingChartId,
    swapCharts,
    duplicateChart,
    closeChart,
    setConfigChartId,
    setChartMode,
    toggleVariable,
    setCharts,
    placingChartId,
    placeChartHere,
    detachChart,
    attachChart,
    moveDetachedChart,
}: {
    theme: "dark" | "light";
    chartItem: ChartWorkspaceItem;
    chartableVariables: ChartVariable[];
    connected: boolean;
    movingChartId: string | null;
    setMovingChartId: React.Dispatch<React.SetStateAction<string | null>>;
    swapCharts: (sourceId: string, targetId: string) => void;
    duplicateChart: (chartId: string) => void;
    closeChart: (chartId: string) => void | Promise<void>;
    setConfigChartId: React.Dispatch<React.SetStateAction<string | null>>;
    setChartMode: (chartId: string, mode: WorkspaceChartMode) => void;
    toggleVariable: (chartId: string, key: string) => void;
    setCharts: React.Dispatch<React.SetStateAction<ChartWorkspaceItem[]>>;
    placingChartId: string | null;
    placeChartHere: (targetChartId: string) => void;
    detachChart: (chartId: string) => void;
    attachChart: (chartId: string) => void | Promise<void>;
    moveDetachedChart: (chartId: string, x: number, y: number) => void;
}) {
    const isMoving = movingChartId === chartItem.id;

    const canReceiveMove =
        (movingChartId !== null && movingChartId !== chartItem.id) ||
        (placingChartId !== null && placingChartId !== chartItem.id);

    const { seriesByKey, loading } = useMeteoChartSeries(
        chartItem.selectedSensorKeys,
        chartItem.timeRange,
    );

    const selectedVariables = useMemo(
        () =>
            chartableVariables.filter((variable) =>
                chartItem.selectedSensorKeys.includes(variable.key),
            ),
        [
            chartItem.selectedSensorKeys.join("|"),
            chartableVariables
                .map((variable) => `${variable.key}:${variable.label}:${variable.unit}`)
                .join("|"),
        ],
    );

    const variablesStillResolving =
        chartItem.selectedSensorKeys.length > 0 && selectedVariables.length === 0;

    const chartConfig: WorkspaceChartConfig = {
        id: chartItem.id,
        title: chartItem.title,
        subtitle:
            chartItem.selectedSensorKeys.length > 0
                ? `${chartItem.selectedSensorKeys.length} sensores selecionados`
                : chartItem.subtitle,
        icon: BarChart3,
        status: connected ? "online" : "offline",
        sourceLabel: connected ? "Meteo Historian" : "Offline",
        mode: chartItem.mode,
        timeRange: chartItem.timeRange,
        interval: chartItem.interval,
        variables: selectedVariables.map((variable, index) => ({
            key: variable.key,
            label: variable.label,
            unit: variable.unit,
            color: getVariableColor(index),
            data: seriesByKey[variable.key] ?? [],
            visible: !(chartItem.hiddenSensorKeys ?? []).includes(variable.key),
        })),
    };

    return (
        <div
            onClick={() => {
                if (movingChartId && movingChartId !== chartItem.id) {
                    swapCharts(movingChartId, chartItem.id);
                }
            }}
            className={
                canReceiveMove
                    ? "relative min-h-0 overflow-hidden rounded-[7px] ring-2 ring-[#4FD1C5]/50 transition"
                    : isMoving
                        ? "relative min-h-0 overflow-hidden rounded-[7px] opacity-60 ring-2 ring-[#4FD1C5]"
                        : "relative min-h-0 overflow-hidden rounded-[7px]"
            }
        >
            <div className="absolute right-4 top-4 z-20 flex items-center gap-1.5">
                <button
                    type="button"
                    title="Configurar"
                    className={floatingIconClass(theme)}
                    onClick={() => setConfigChartId(chartItem.id)}
                >
                    <Cog className="h-4 w-4" />
                </button>

                <button
                    type="button"
                    title="Duplicar"
                    className={floatingIconClass(theme)}
                    onClick={() => duplicateChart(chartItem.id)}
                >
                    <Copy className="h-4 w-4" />
                </button>

                <button
                    type="button"
                    title={chartItem.detached ? "Repor janela" : "Destacar janela"}
                    className={floatingIconClass(theme)}
                    onClick={() =>
                        chartItem.detached
                            ? attachChart(chartItem.id)
                            : detachChart(chartItem.id)
                    }
                >
                    <Maximize2 className="h-4 w-4" />
                </button>

                <button
                    type="button"
                    title="Fechar"
                    className={floatingIconClass(theme)}
                    onClick={() => void closeChart(chartItem.id)}
                >
                    <X className="h-4 w-4" />
                </button>
            </div>

            {canReceiveMove && (
                <div className="absolute inset-0 z-30 flex items-center justify-center rounded-[7px] bg-[#07101B]/55 backdrop-blur-[2px]">
                    <button
                        type="button"
                        onClick={(event) => {
                            event.stopPropagation();

                            if (placingChartId && placingChartId !== chartItem.id) {
                                placeChartHere(chartItem.id);
                                return;
                            }

                            if (movingChartId && movingChartId !== chartItem.id) {
                                swapCharts(movingChartId, chartItem.id);
                            }
                        }}
                        className="rounded-[6px] bg-[#4FD1C5] px-5 py-2.5 text-sm font-black text-[#07101B] shadow-xl transition hover:bg-[#63E6D8]"
                    >
                        Colocar aqui
                    </button>
                </div>
            )}

            <WorkspaceChart
                theme={theme}
                chart={chartConfig}
                configuredVariableCount={chartItem.selectedSensorKeys.length}
                loading={loading || variablesStillResolving}
                detached={chartItem.detached}
                onDetach={() => detachChart(chartItem.id)}
                onAttach={() => attachChart(chartItem.id)}
                onTimeRangeChange={(range) =>
                    setCharts((current) =>
                        current.map((chart) =>
                            chart.id === chartItem.id
                                ? { ...chart, timeRange: range }
                                : chart,
                        ),
                    )
                }
                onIntervalChange={(interval) =>
                    setCharts((current) =>
                        current.map((chart) =>
                            chart.id === chartItem.id
                                ? { ...chart, interval }
                                : chart,
                        ),
                    )
                }
                dragHandle={
                    <button
                        type="button"
                        onClick={(event) => {
                            event.stopPropagation();

                            setMovingChartId((current) =>
                                current === chartItem.id ? null : chartItem.id,
                            );
                        }}
                        title={
                            isMoving
                                ? "Cancelar movimento"
                                : "Escolher este gráfico para mover"
                        }
                        className={
                            isMoving
                                ? `${RADIUS} border border-[#4FD1C5] bg-[#4FD1C5] p-2 text-[#07101B]`
                                : theme === "dark"
                                    ? `${RADIUS} border border-[#263247] bg-[#111A2B] p-2 text-[#7F8CA3] transition hover:text-white`
                                    : `${RADIUS} border border-[#D7DEE8] bg-white p-2 text-slate-500 transition hover:text-[#0F172A]`
                        }
                    >
                        <GripVertical className="h-4 w-4" />
                    </button>
                }
                onModeChange={(mode) => setChartMode(chartItem.id, mode)}
                onVariableToggle={(variableKey) =>
                    toggleVariable(chartItem.id, variableKey)
                }
                onHeaderPointerDown={
                    chartItem.detached
                        ? (event) => {
                            const startX = event.clientX;
                            const startY = event.clientY;
                            const initialX = chartItem.windowX ?? 120;
                            const initialY = chartItem.windowY ?? 120;

                            const handlePointerMove = (moveEvent: PointerEvent) => {
                                moveDetachedChart(
                                    chartItem.id,
                                    initialX + moveEvent.clientX - startX,
                                    initialY + moveEvent.clientY - startY,
                                );
                            };

                            const handlePointerUp = () => {
                                window.removeEventListener(
                                    "pointermove",
                                    handlePointerMove,
                                );
                                window.removeEventListener(
                                    "pointerup",
                                    handlePointerUp,
                                );
                            };

                            window.addEventListener("pointermove", handlePointerMove);
                            window.addEventListener("pointerup", handlePointerUp);
                        }
                        : undefined
                }
            />
        </div>
    );
}

function useMeteoChartSeries(
    selectedSensorKeys: string[],
    timeRange: WorkspaceChartTimeRange,
) {
    const [seriesByKey, setSeriesByKey] = useState<Record<string, ChartPoint[]>>({});
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        if (selectedSensorKeys.length === 0) {
            setSeriesByKey({});
            setLoading(false);
            return;
        }

        const controller = new AbortController();

        async function loadSeries() {
            try {
                const to = new Date();
                const from = new Date(
                    to.getTime() - timeRangeToMilliseconds(timeRange),
                );

                setLoading(true);

                const entries = await Promise.all(
                    selectedSensorKeys.map(async (key) => {
                        const params = new URLSearchParams({
                            key,
                            from: from.toISOString(),
                            to: to.toISOString(),
                        });

                        const response = await fetch(
                            `${BACKEND_URL}/api/historian/series?${params.toString()}`,
                            {
                                signal: controller.signal,
                                cache: "no-store",
                                headers: {
                                    Accept: "application/json",
                                    "Cache-Control": "no-cache",
                                    Pragma: "no-cache",
                                },
                            },
                        );

                        if (!response.ok) {
                            const text = await response.text();
                            throw new Error(
                                `Failed to load meteo history for ${key}: ${response.status} ${text}`,
                            );
                        }

                        const payload = (await response.json()) as HistorianPoint[];

                        return [
                            key,
                            payload.map((point) => ({
                                timestamp: getHistorianPointTimestamp(point),
                                value: getHistorianPointValue(point),
                            })),
                        ] as const;
                    }),
                );

                setSeriesByKey(Object.fromEntries(entries));
            } catch (error) {
                if (controller.signal.aborted) return;

                console.error("[MeteoCharts ERROR]", error);
                setSeriesByKey({});
            } finally {
                if (!controller.signal.aborted) {
                    setLoading(false);
                }
            }
        }

        void loadSeries();

        return () => {
            controller.abort();
        };
    }, [selectedSensorKeys.join("|"), timeRange]);

    return { seriesByKey, loading };
}

type ChartPoint = {
    timestamp: string;
    value: number;
};

function getHistorianPointTimestamp(point: HistorianPoint): string {
    return point.timestamp;
}

function getHistorianPointValue(point: HistorianPoint): number {
    if (typeof point.numericValue === "number") {
        return point.numericValue;
    }

    const rawValue = point.value ?? point.v ?? point.total;

    if (typeof rawValue === "number") return rawValue;

    if (typeof rawValue === "string" && rawValue.trim() !== "") {
        const parsed = Number(rawValue);
        return Number.isFinite(parsed) ? parsed : 0;
    }

    return 0;
}

function timeRangeToMilliseconds(timeRange: WorkspaceChartTimeRange): number {
    if (timeRange === "15m") return 15 * 60 * 1000;
    if (timeRange === "24h") return 24 * 60 * 60 * 1000;
    if (timeRange === "7d") return 7 * 24 * 60 * 60 * 1000;
    if (timeRange === "30d") return 30 * 24 * 60 * 60 * 1000;

    return 24 * 60 * 60 * 1000;
}

function floatingIconClass(theme: "dark" | "light") {
    return theme === "dark"
        ? `${RADIUS} grid h-8 w-8 place-items-center border border-[#263247] bg-[#111A2B] text-[#A8B3C7] transition hover:text-white`
        : `${RADIUS} grid h-8 w-8 place-items-center border border-[#D7DEE8] bg-white text-slate-500 transition hover:text-[#0F172A]`;
}

function SavedChartsDropdown({
    theme,
    charts,
    search,
    onSearchChange,
    onClose,
    onStartPlacement,
    onDelete,
}: {
    theme: "dark" | "light";
    charts: ChartWorkspaceItem[];
    search: string;
    onSearchChange: (value: string) => void;
    onClose: () => void;
    onStartPlacement: (chartId: string) => void;
    onDelete: (chartId: string) => void | Promise<void>;
}) {
    const isDark = theme === "dark";

    return (
        <div
            className={
                isDark
                    ? `${RADIUS} absolute right-0 top-[calc(100%+8px)] z-40 w-[430px] border border-[#263247] bg-[#0E1726] p-3 shadow-2xl`
                    : `${RADIUS} absolute right-0 top-[calc(100%+8px)] z-40 w-[430px] border border-[#D7DEE8] bg-white p-3 shadow-2xl`
            }
        >
            <div className="mb-3 flex items-center justify-between">
                <div>
                    <h2 className="text-sm font-black">Gráficos Guardados</h2>
                    <p
                        className={
                            isDark
                                ? "mt-1 text-xs text-[#7F8CA3]"
                                : "mt-1 text-xs text-slate-500"
                        }
                    >
                        {charts.length}/10 gráficos no workspace.
                    </p>
                </div>

                <button type="button" onClick={onClose}>
                    <X className="h-4 w-4" />
                </button>
            </div>

            <div
                className={
                    isDark
                        ? `${RADIUS} mb-3 flex h-10 items-center gap-2 border border-[#263247] bg-[#07101B] px-3 text-sm text-[#7F8CA3]`
                        : `${RADIUS} mb-3 flex h-10 items-center gap-2 border border-[#D7DEE8] bg-[#F8FAFC] px-3 text-sm text-slate-500`
                }
            >
                <Search className="h-4 w-4" />
                <input
                    value={search}
                    onChange={(event) => onSearchChange(event.target.value)}
                    placeholder="Pesquisar gráficos..."
                    className="w-full bg-transparent outline-none placeholder:text-inherit"
                />
            </div>

            <div className="max-h-[280px] space-y-2 overflow-y-auto pr-1">
                {charts.map((chart) => (
                    <div
                        key={chart.id}
                        className={
                            isDark
                                ? `${RADIUS} flex w-full items-center justify-between gap-3 border border-[#263247] bg-[#111A2B] px-3 py-3 transition hover:border-[#36506D]`
                                : `${RADIUS} flex w-full items-center justify-between gap-3 border border-[#D7DEE8] bg-[#F8FAFC] px-3 py-3 transition hover:bg-white`
                        }
                    >
                        <div className="min-w-0">
                            <p className="truncate text-sm font-black">{chart.title}</p>
                            <p
                                className={
                                    isDark
                                        ? "mt-1 truncate text-xs text-[#7F8CA3]"
                                        : "mt-1 truncate text-xs text-slate-500"
                                }
                            >
                                {chart.selectedSensorKeys.length} sensores ·{" "}
                                {chart.timeRange} · {chart.interval}
                            </p>
                        </div>

                        <div className="flex shrink-0 items-center gap-3">
                            {chart.detached && !chart.hidden ? (
                                <span className="text-xs font-black text-[#FACC15]">
                                    Destacado
                                </span>
                            ) : chart.hidden || chart.collapsed ? (
                                <button
                                    type="button"
                                    onClick={() => onStartPlacement(chart.id)}
                                    title="Abrir gráfico"
                                    className="text-[#7F8CA3] transition hover:text-[#4FD1C5]"
                                >
                                    <Play className="h-4 w-4" />
                                </button>
                            ) : (
                                <span className="text-xs font-black text-[#4FD1C5]">
                                    Aberto
                                </span>
                            )}

                            <button
                                type="button"
                                onClick={() => void onDelete(chart.id)}
                                title="Eliminar gráfico"
                                className="text-[#7F8CA3] transition hover:text-red-400"
                            >
                                <Trash2 className="h-4 w-4" />
                            </button>
                        </div>
                    </div>
                ))}

                {charts.length === 0 && (
                    <div
                        className={
                            isDark
                                ? `${RADIUS} border border-dashed border-[#263247] px-4 py-6 text-center text-sm font-bold text-[#7F8CA3]`
                                : `${RADIUS} border border-dashed border-[#D7DEE8] px-4 py-6 text-center text-sm font-bold text-slate-500`
                        }
                    >
                        Nenhum gráfico guardado.
                    </div>
                )}
            </div>
        </div>
    );
}

function NewChartModal({
    theme,
    variables,
    chartNumber,
    onClose,
    onCreate,
}: {
    theme: "dark" | "light";
    variables: ChartVariable[];
    chartNumber: number;
    onClose: () => void;
    onCreate: (chart: {
        title: string;
        mode: WorkspaceChartMode;
        selectedSensorKeys: string[];
    }) => void;
}) {
    const isDark = theme === "dark";
    const [title, setTitle] = useState(`Novo Gráfico ${chartNumber}`);
    const [mode, setMode] = useState<WorkspaceChartMode>("line");
    const [search, setSearch] = useState("");
    const [selectedSensorKeys, setSelectedSensorKeys] = useState<string[]>([]);

    const filteredVariables = variables.filter((variable) =>
        `${variable.label} ${variable.category} ${variable.group} ${variable.unit}`
            .toLowerCase()
            .includes(search.toLowerCase()),
    );

    const toggleVariable = (key: string) => {
        setSelectedSensorKeys((current) => {
            const alreadySelected = current.includes(key);

            if (alreadySelected) {
                return current.filter((item) => item !== key);
            }

            if (current.length >= MAX_VARIABLES_PER_CHART) {
                return current;
            }

            return [...current, key];
        });
    };

    const canCreate = title.trim().length > 0 && selectedSensorKeys.length > 0;

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/55 p-6">
            <div
                className={
                    isDark
                        ? `${RADIUS} w-full max-w-[760px] border border-[#263247] bg-[#0E1726] shadow-2xl`
                        : `${RADIUS} w-full max-w-[760px] border border-[#D7DEE8] bg-white shadow-2xl`
                }
            >
                <header
                    className={
                        isDark
                            ? "flex items-center justify-between border-b border-[#263247] px-6 py-5"
                            : "flex items-center justify-between border-b border-[#D7DEE8] px-6 py-5"
                    }
                >
                    <div>
                        <p
                            className={
                                isDark
                                    ? "text-xs font-black uppercase tracking-[0.2em] text-[#4FD1C5]"
                                    : "text-xs font-black uppercase tracking-[0.2em] text-[#0F766E]"
                            }
                        >
                            Novo gráfico
                        </p>

                        <h2 className="mt-1 text-xl font-black">
                            Criar gráfico meteorológico
                        </h2>
                    </div>

                    <button
                        type="button"
                        onClick={onClose}
                        className={
                            isDark
                                ? `${RADIUS} p-2 text-[#A8B3C7] transition hover:bg-[#111A2B] hover:text-white`
                                : `${RADIUS} p-2 text-slate-500 transition hover:bg-[#F8FAFC] hover:text-[#0F172A]`
                        }
                    >
                        <X className="h-5 w-5" />
                    </button>
                </header>

                <main className="grid gap-6 p-6 md:grid-cols-[260px_minmax(0,1fr)]">
                    <section className="space-y-4">
                        <div>
                            <label className="mb-2 block text-sm font-black">Nome</label>
                            <input
                                value={title}
                                onChange={(event) => setTitle(event.target.value)}
                                className={
                                    isDark
                                        ? `${RADIUS} h-11 w-full border border-[#263247] bg-[#07101B] px-3 text-sm font-bold text-white outline-none`
                                        : `${RADIUS} h-11 w-full border border-[#D7DEE8] bg-[#F8FAFC] px-3 text-sm font-bold text-[#0F172A] outline-none`
                                }
                            />
                        </div>

                        <div>
                            <label className="mb-2 block text-sm font-black">
                                Tipo de gráfico
                            </label>

                            <div className="grid grid-cols-3 gap-2">
                                <ModeButton
                                    theme={theme}
                                    active={mode === "line"}
                                    icon={<LineChart className="h-4 w-4" />}
                                    label="Linha"
                                    onClick={() => setMode("line")}
                                />
                                <ModeButton
                                    theme={theme}
                                    active={mode === "area"}
                                    icon={<AreaChart className="h-4 w-4" />}
                                    label="Área"
                                    onClick={() => setMode("area")}
                                />
                                <ModeButton
                                    theme={theme}
                                    active={mode === "bar"}
                                    icon={<BarChart3 className="h-4 w-4" />}
                                    label="Barras"
                                    onClick={() => setMode("bar")}
                                />
                            </div>
                        </div>

                        <div
                            className={
                                isDark
                                    ? `${RADIUS} border border-[#263247] bg-[#111A2B] p-3`
                                    : `${RADIUS} border border-[#D7DEE8] bg-[#F8FAFC] p-3`
                            }
                        >
                            <p className="text-xs font-black uppercase tracking-[0.18em] text-[#7F8CA3]">
                                Selecionadas
                            </p>

                            <p className="mt-2 text-sm font-black">
                                {selectedSensorKeys.length}/{MAX_VARIABLES_PER_CHART}
                            </p>
                        </div>
                    </section>

                    <section>
                        <label className="mb-2 block text-sm font-black">
                            Sensores meteorológicos
                        </label>

                        <div
                            className={
                                isDark
                                    ? `${RADIUS} mb-3 flex h-10 items-center gap-2 border border-[#263247] bg-[#07101B] px-3 text-sm text-[#7F8CA3]`
                                    : `${RADIUS} mb-3 flex h-10 items-center gap-2 border border-[#D7DEE8] bg-[#F8FAFC] px-3 text-sm text-slate-500`
                            }
                        >
                            <Search className="h-4 w-4" />
                            <input
                                value={search}
                                onChange={(event) => setSearch(event.target.value)}
                                placeholder="Pesquisar sensor..."
                                className="w-full bg-transparent outline-none placeholder:text-inherit"
                            />
                        </div>

                        <div className="max-h-[320px] space-y-2 overflow-y-auto pr-1">
                            {filteredVariables.map((variable, index) => {
                                const active = selectedSensorKeys.includes(variable.key);

                                return (
                                    <VariableRow
                                        key={variable.key}
                                        theme={theme}
                                        variable={variable}
                                        color={getVariableColor(index)}
                                        active={active}
                                        disabled={
                                            !active &&
                                            selectedSensorKeys.length >=
                                            MAX_VARIABLES_PER_CHART
                                        }
                                        onClick={() => toggleVariable(variable.key)}
                                    />
                                );
                            })}

                            {filteredVariables.length === 0 && (
                                <EmptyVariableList theme={theme} />
                            )}
                        </div>
                    </section>
                </main>

                <footer
                    className={
                        isDark
                            ? "flex justify-end gap-3 border-t border-[#263247] px-6 py-5"
                            : "flex justify-end gap-3 border-t border-[#D7DEE8] px-6 py-5"
                    }
                >
                    <button
                        type="button"
                        onClick={onClose}
                        className={
                            isDark
                                ? `${RADIUS} border border-[#263247] bg-[#111A2B] px-5 py-2.5 text-sm font-bold text-white`
                                : `${RADIUS} border border-[#D7DEE8] bg-[#F8FAFC] px-5 py-2.5 text-sm font-bold text-[#0F172A]`
                        }
                    >
                        Cancelar
                    </button>

                    <button
                        type="button"
                        disabled={!canCreate}
                        onClick={() =>
                            onCreate({
                                title: title.trim(),
                                mode,
                                selectedSensorKeys,
                            })
                        }
                        className={
                            canCreate
                                ? `flex items-center gap-2 ${RADIUS} bg-[#18B8A6] px-5 py-2.5 text-sm font-black text-white transition hover:bg-[#21C7B5]`
                                : `flex cursor-not-allowed items-center gap-2 ${RADIUS} bg-[#18B8A6]/40 px-5 py-2.5 text-sm font-black text-white`
                        }
                    >
                        <Plus className="h-4 w-4" />
                        Criar
                    </button>
                </footer>
            </div>
        </div>
    );
}

function VariableRow({
    theme,
    variable,
    color,
    active,
    disabled,
    onClick,
}: {
    theme: "dark" | "light";
    variable: ChartVariable;
    color: string;
    active: boolean;
    disabled: boolean;
    onClick: () => void;
}) {
    const isDark = theme === "dark";

    return (
        <button
            type="button"
            disabled={disabled}
            onClick={onClick}
            className={
                active
                    ? isDark
                        ? `${RADIUS} flex h-12 w-full items-center justify-between border border-[#36506D] bg-[#132033] px-3 text-left text-sm font-bold text-white`
                        : `${RADIUS} flex h-12 w-full items-center justify-between border border-[#0F766E]/30 bg-[#ECFDF5] px-3 text-left text-sm font-bold text-[#0F172A]`
                    : disabled
                        ? isDark
                            ? `${RADIUS} flex h-12 w-full cursor-not-allowed items-center justify-between border border-[#263247] bg-[#111A2B]/50 px-3 text-left text-sm font-semibold text-[#7F8CA3]/50`
                            : `${RADIUS} flex h-12 w-full cursor-not-allowed items-center justify-between border border-[#D7DEE8] bg-[#F8FAFC]/60 px-3 text-left text-sm font-semibold text-slate-400`
                        : isDark
                            ? `${RADIUS} flex h-12 w-full items-center justify-between border border-[#263247] bg-[#111A2B] px-3 text-left text-sm font-semibold text-white transition hover:border-[#36506D]`
                            : `${RADIUS} flex h-12 w-full items-center justify-between border border-[#D7DEE8] bg-[#F8FAFC] px-3 text-left text-sm font-semibold text-[#0F172A] transition hover:bg-white`
            }
        >
            <span className="flex min-w-0 items-center gap-2">
                <span
                    className="h-3 w-3 shrink-0 rounded-full"
                    style={{ backgroundColor: color }}
                />

                <span className="min-w-0">
                    <span className="block truncate">{variable.label}</span>
                    <span
                        className={
                            isDark
                                ? "mt-0.5 block truncate text-xs font-bold text-[#7F8CA3]"
                                : "mt-0.5 block truncate text-xs font-bold text-slate-500"
                        }
                    >
                        {variable.group} · {variable.category}
                        {variable.unit ? ` · ${variable.unit}` : ""}
                    </span>
                </span>
            </span>

            <span
                className={
                    active
                        ? "text-xs font-black text-[#4FD1C5]"
                        : "text-xs font-bold text-[#7F8CA3]"
                }
            >
                {active ? "ON" : "OFF"}
            </span>
        </button>
    );
}

function EmptyVariableList({ theme }: { theme: "dark" | "light" }) {
    const isDark = theme === "dark";

    return (
        <div
            className={
                isDark
                    ? `${RADIUS} border border-dashed border-[#263247] px-4 py-6 text-center text-sm font-bold text-[#7F8CA3]`
                    : `${RADIUS} border border-dashed border-[#D7DEE8] px-4 py-6 text-center text-sm font-bold text-slate-500`
            }
        >
            Nenhum sensor encontrado.
        </div>
    );
}

function layoutGridClass(layoutMode: ChartLayoutMode) {
    if (layoutMode === "fourGrid") {
        return "grid min-h-0 flex-1 grid-cols-2 grid-rows-2 gap-3 overflow-hidden";
    }

    if (layoutMode === "twoColumns") {
        return "grid min-h-0 flex-1 grid-cols-2 gap-3 overflow-hidden";
    }

    if (layoutMode === "twoRows") {
        return "grid min-h-0 flex-1 grid-rows-2 gap-3 overflow-hidden";
    }

    return "grid min-h-0 flex-1 gap-3 overflow-hidden";
}

function getVisibleSlotCount(layoutMode: ChartLayoutMode) {
    if (layoutMode === "single") return 1;
    if (layoutMode === "twoColumns") return 2;
    if (layoutMode === "twoRows") return 2;
    return 4;
}

function LayoutButton({
    theme,
    active,
    icon,
    title,
    onClick,
}: {
    theme: "dark" | "light";
    active: boolean;
    icon: React.ReactNode;
    title: string;
    onClick: () => void;
}) {
    const isDark = theme === "dark";

    return (
        <button
            type="button"
            title={title}
            aria-label={title}
            onClick={onClick}
            className={
                active
                    ? isDark
                        ? `${RADIUS} grid h-10 w-10 place-items-center bg-[#4FD1C5] text-[#07101B]`
                        : `${RADIUS} grid h-10 w-10 place-items-center bg-[#0F766E] text-white`
                    : isDark
                        ? `${RADIUS} grid h-10 w-10 place-items-center border border-[#263247] bg-[#111A2B] text-[#A8B3C7] transition hover:border-[#36506D] hover:text-white`
                        : `${RADIUS} grid h-10 w-10 place-items-center border border-[#D7DEE8] bg-[#F8FAFC] text-slate-600 transition hover:bg-white hover:text-[#0F172A]`
            }
        >
            {icon}
        </button>
    );
}

function ModeButton({
    theme,
    active,
    icon,
    label,
    onClick,
}: {
    theme: "dark" | "light";
    active: boolean;
    icon?: React.ReactNode;
    label: string;
    onClick: () => void;
}) {
    return (
        <button
            type="button"
            onClick={onClick}
            className={
                active
                    ? theme === "dark"
                        ? `${RADIUS} flex items-center justify-center gap-2 bg-[#4FD1C5] px-3 py-2 text-xs font-black text-[#07101B]`
                        : `${RADIUS} flex items-center justify-center gap-2 bg-[#0F766E] px-3 py-2 text-xs font-black text-white`
                    : theme === "dark"
                        ? `${RADIUS} flex items-center justify-center gap-2 border border-[#263247] bg-[#111A2B] px-3 py-2 text-xs font-bold text-[#A8B3C7]`
                        : `${RADIUS} flex items-center justify-center gap-2 border border-[#D7DEE8] bg-[#F8FAFC] px-3 py-2 text-xs font-bold text-slate-600`
            }
        >
            {icon}
            {label}
        </button>
    );
}

function EmptyWorkspace({
    theme,
    canAddMoreCharts,
    onAddChart,
    onOpenSaved,
}: {
    theme: "dark" | "light";
    canAddMoreCharts: boolean;
    onAddChart: () => void;
    onOpenSaved: () => void;
}) {
    const isDark = theme === "dark";

    return (
        <section
            className={
                isDark
                    ? `${RADIUS} flex min-h-0 flex-1 items-center justify-center border border-dashed border-[#33445F] bg-[#0E1726]/70`
                    : `${RADIUS} flex min-h-0 flex-1 items-center justify-center border border-dashed border-[#CBD5E1] bg-white`
            }
        >
            <div className="max-w-[420px] text-center">
                <div
                    className={
                        isDark
                            ? "mx-auto grid h-16 w-16 place-items-center rounded-2xl border border-[#263247] bg-[#111A2B] text-[#4FD1C5]"
                            : "mx-auto grid h-16 w-16 place-items-center rounded-2xl border border-[#D7DEE8] bg-[#F8FAFC] text-[#0F766E]"
                    }
                >
                    <BarChart3 className="h-8 w-8" />
                </div>

                <h2
                    className={
                        isDark
                            ? "mt-5 text-xl font-black text-white"
                            : "mt-5 text-xl font-black text-[#0F172A]"
                    }
                >
                    Nenhum gráfico aberto
                </h2>

                <p
                    className={
                        isDark
                            ? "mt-3 text-sm leading-6 text-[#A8B3C7]"
                            : "mt-3 text-sm leading-6 text-slate-600"
                    }
                >
                    Abra um gráfico guardado ou crie um novo gráfico meteorológico
                    para continuar.
                </p>

                <div className="mt-6 flex items-center justify-center gap-3">
                    <button
                        type="button"
                        disabled={!canAddMoreCharts}
                        onClick={onAddChart}
                        className={
                            canAddMoreCharts
                                ? `inline-flex h-11 items-center gap-3 ${RADIUS} bg-[#18B8A6] px-5 text-sm font-black text-white transition hover:bg-[#21C7B5]`
                                : `inline-flex h-11 cursor-not-allowed items-center gap-3 ${RADIUS} bg-[#18B8A6]/40 px-5 text-sm font-black text-white`
                        }
                    >
                        <Plus className="h-5 w-5" />
                        Novo Gráfico
                    </button>

                    <button
                        type="button"
                        onClick={onOpenSaved}
                        className={
                            isDark
                                ? `inline-flex h-11 items-center gap-3 ${RADIUS} border border-[#263247] bg-[#111A2B] px-5 text-sm font-black text-white`
                                : `inline-flex h-11 items-center gap-3 ${RADIUS} border border-[#D7DEE8] bg-[#F8FAFC] px-5 text-sm font-black text-[#0F172A]`
                        }
                    >
                        <Search className="h-5 w-5" />
                        Abrir Guardado
                    </button>
                </div>
            </div>
        </section>
    );
}

function getVariableColor(index: number) {
    const colors = [
        "#4FD1C5",
        "#3B82F6",
        "#FACC15",
        "#7DD3FC",
        "#A5B4FC",
        "#FB7185",
    ];

    return colors[index % colors.length];
}

export default MeteoChartsPage;