import { useEffect, useMemo, useRef, useState } from "react";
import { emit } from "@tauri-apps/api/event";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { X, Minus, Maximize2, PanelTop, Cog, Square } from "lucide-react";
import { ChartConfigModal } from "../components/ChartConfigModal";

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

import { useTelemetryCatalog } from "../../telemetry/hooks/useTelemetryCatalog";
import { useTelemetryChartSeries } from "../../telemetry/hooks/useTelemetryChartSeries";

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

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

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

export function ChartWindowPage({ theme }: ChartWindowPageProps) {
    const isDark = theme === "dark";
    const parts = window.location.pathname.split("/").filter(Boolean);
    const chartId = parts[parts.length - 1] ?? "";

    const params = new URLSearchParams(window.location.search);

    const scope =
        (params.get("scope") as "GLOBAL" | "CLIMATE") ?? "GLOBAL";

    const channel =
        (params.get("channel") as "maincharts" | "climatecharts") ??
        "maincharts";

    const { chartableVariables, connected } = useTelemetryCatalog();

    const [charts, setCharts] = useState<ChartWorkspaceItem[]>([]);
    const [configOpen, setConfigOpen] = useState(false);

    const currentWindow = getCurrentWindow();
    const latestChartRef = useRef<ChartWorkspaceItem | null>(null);

    const titleBarClass = isDark
        ? "flex h-9 shrink-0 items-center bg-[#1F232A] text-[#D7DEE8]"
        : "flex h-9 shrink-0 items-center border-b border-[#D7DEE8] bg-white text-[#0F172A]";

    const titleButtonClass = isDark
        ? "grid h-9 w-11 place-items-center text-[#A8B3C7] transition hover:bg-white/10 hover:text-white"
        : "grid h-9 w-11 place-items-center text-slate-500 transition hover:bg-[#F8FAFC] hover:text-[#0F172A]";

    const closeButtonClass = isDark
        ? "grid h-9 w-11 place-items-center text-[#A8B3C7] transition hover:bg-red-500 hover:text-white"
        : "grid h-9 w-11 place-items-center text-slate-500 transition hover:bg-red-500 hover:text-white";

    useChartWorkspacePersistence({
        scope,
        layoutMode: "fourGrid",
        charts,
        onLoaded: (workspace) => {
            const loadedCharts = workspace.charts as ChartWorkspaceItem[];
            setCharts(loadedCharts);

            latestChartRef.current =
                loadedCharts.find((item) => item.id === chartId) ?? null;
        },
    });

    const chart = useMemo(
        () => charts.find((item) => item.id === chartId) ?? null,
        [charts, chartId],
    );

    useEffect(() => {
        latestChartRef.current = chart;
    }, [chart]);

    const emitMainUpdate = async (patch: Partial<ChartWorkspaceItem>) => {
        await emit(`${channel}://update-chart`, {
            chartId,
            patch,
        });
    };

    const emitMainHidden = async () => {
        await emit(`${channel}://hide-chart`, {
            chartId,
            chart: latestChartRef.current,
        });
    };

    const emitMainAttached = async () => {
        await emit(`${channel}://attach-chart`, {
            chartId,
            chart: latestChartRef.current,
        });
    };

    useEffect(() => {
        const unlistenPromise = currentWindow.onCloseRequested(async (event) => {
            event.preventDefault();

            try {
                await emitMainHidden();
            } finally {
                await currentWindow.destroy();
            }
        });

        return () => {
            void unlistenPromise.then((unlisten) => unlisten());
        };
    }, [chartId]);

    const applyLocalPatch = (patch: Partial<ChartWorkspaceItem>) => {
        setCharts((current) =>
            current.map((item) => {
                if (item.id !== chartId) return item;

                const next = {
                    ...item,
                    ...patch,
                };

                latestChartRef.current = next;

                return next;
            }),
        );
    };

    const updateChart = (patch: Partial<ChartWorkspaceItem>) => {
        applyLocalPatch(patch);

        void emitMainUpdate(patch).catch((error) => {
            console.error("Failed to sync chart update to main window", error);
        });
    };

    const toggleVariable = (variableKey: string) => {
        const currentChart = latestChartRef.current;
        if (!currentChart) return;

        const hiddenSensorKeys = currentChart.hiddenSensorKeys ?? [];
        const isHidden = hiddenSensorKeys.includes(variableKey);

        const nextHiddenSensorKeys = isHidden
            ? hiddenSensorKeys.filter((key) => key !== variableKey)
            : [...hiddenSensorKeys, variableKey];

        updateChart({
            hiddenSensorKeys: nextHiddenSensorKeys,
        });
    };

    const { seriesByKey, loading } = useTelemetryChartSeries(
        chart?.selectedSensorKeys ?? [],
        chart?.timeRange ?? "24h",
        chart?.interval ?? "5m",
    );

    const selectedVariables = useMemo(
        () =>
            chartableVariables.filter((variable) =>
                chart?.selectedSensorKeys.includes(variable.key),
            ),
        [chart?.selectedSensorKeys, chartableVariables],
    );

    const attachAndClose = async () => {
        try {
            await emitMainAttached();
        } catch (error) {
            console.error("Failed to attach chart", error);
        }

        await currentWindow.destroy();
    };

    const closeAndHide = async () => {
        try {
            await emitMainHidden();
        } catch (error) {
            console.error("Failed to hide chart", error);
        }

        await currentWindow.destroy();
    };

    if (!chart && charts.length === 0) {
        return null;
    }

    if (!chart) {
        return (
            <div
                className={
                    isDark
                        ? "flex h-screen items-center justify-center bg-[#07101B] text-sm font-bold text-[#7F8CA3]"
                        : "flex h-screen items-center justify-center bg-white text-sm font-bold text-slate-500"
                }
            >
                Gráfico não encontrado.
            </div>
        );
    }

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

    const chartConfig: WorkspaceChartConfig = {
        id: chart.id,
        title: "",
        subtitle: "",
        icon: Maximize2,
        status: connected ? "online" : "offline",
        sourceLabel: connected ? "Telemetry" : "Offline",
        mode: chart.mode,
        timeRange: chart.timeRange,
        interval: chart.interval,
        variables: chartableVariables
            .filter((variable) =>
                chart.selectedSensorKeys.includes(variable.key),
            )
            .map((variable, index) => ({
                key: variable.key,
                label: variable.label,
                unit: variable.unit,
                color: getVariableColor(index),
                data: seriesByKey[variable.key] ?? [],
                visible: !(chart.hiddenSensorKeys ?? []).includes(variable.key),
            })),
    };

    return (
        <div
            className={
                isDark
                    ? "flex h-screen flex-col overflow-hidden bg-[#07101B] text-white"
                    : "flex h-screen flex-col overflow-hidden bg-white text-[#0F172A]"
            }
        >
            <header className={titleBarClass}>
                <div
                    className="flex h-full flex-1 items-center px-3 text-xs font-black"
                    onPointerDown={() => {
                        void currentWindow.startDragging();
                    }}
                >
                    {chart.title}
                </div>

                <div className="flex h-full items-center">
                    <button type="button" title="Configurar" onClick={() => setConfigOpen(true)} className={titleButtonClass}>
                        <Cog className="h-4 w-4" />
                    </button>

                    <button type="button" title="Repor no grid" onClick={attachAndClose} className={titleButtonClass}>
                        <PanelTop className="h-4 w-4" />
                    </button>

                    <button type="button" title="Minimizar" onClick={() => currentWindow.minimize()} className={titleButtonClass}>
                        <Minus className="h-4 w-4" />
                    </button>

                    <button type="button" title="Maximizar" onClick={() => currentWindow.toggleMaximize()} className={titleButtonClass}>
                        <Square className="h-3.5 w-3.5" />
                    </button>

                    <button type="button" title="Fechar" onClick={closeAndHide} className={closeButtonClass}>
                        <X className="h-4 w-4" />
                    </button>
                </div>
            </header>

            <main
                className={
                    isDark
                        ? "min-h-0 flex-1 bg-[#07101B] [&>section]:h-full [&>section]:rounded-none [&>section]:border-0"
                        : "min-h-0 flex-1 bg-white [&>section]:h-full [&>section]:rounded-none [&>section]:border-0 [&>section]:shadow-none"
                }
            >
                <WorkspaceChart
                    theme={theme}
                    chart={chartConfig}
                    detached
                    loading={loading || variablesStillResolving}
                    configuredVariableCount={chart.selectedSensorKeys.length}
                    onModeChange={(mode) => updateChart({ mode })}
                    onVariableToggle={toggleVariable}
                    onTimeRangeChange={(timeRange) => updateChart({ timeRange })}
                    onIntervalChange={(interval) => updateChart({ interval })}
                />
            </main>

            {configOpen && (
                <ChartConfigModal
                    theme={theme}
                    chart={chart}
                    variables={chartableVariables}
                    onClose={() => setConfigOpen(false)}
                    onSave={async (updatedChart) => {
                        setCharts((current) =>
                            current.map((item) =>
                                item.id === updatedChart.id
                                    ? { ...item, ...updatedChart }
                                    : item,
                            ),
                        );

                        latestChartRef.current = {
                            ...chart,
                            ...updatedChart,
                        };

                        await emit(`${channel}://replace-chart`, {
                            chart: updatedChart,
                        }).catch((error) => {
                            console.error("Failed to replace chart in main window", error);
                        });

                        setConfigOpen(false);
                    }}
                />
            )}
        </div>
    );
}

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

    return colors[index % colors.length];
}

export default ChartWindowPage;