import { useMemo } from "react";
import type { LucideIcon } from "lucide-react";
import {
    Droplet,
    Gauge,
    Home,
    Layers3,
    Lightbulb,
    Thermometer,
    Wind,
} from "lucide-react";

import type { ModuleSensorResponse } from "../../../types/meteo";
import { useClimateModuleStream } from "../../climate/hooks/useClimateModuleStream";

export type SynopticVariableGroup = "Clima" | "Rega";

export type SynopticVariable = {
    id: string;
    sensorId: string;
    key: string;
    group: SynopticVariableGroup;
    label: string;
    value: string | number | boolean | null;
    unit: string;
    timestamp?: string;
    connected: boolean;
    icon: LucideIcon;
    color: string;
};

export function useSynopticVariables() {
    const climate = useClimateModuleStream();

    const variables = useMemo<SynopticVariable[]>(
        () =>
            toSynopticVariables({
                sensors: climate.sensors,
                group: "Clima",
                connected: climate.connected,
                fallbackTimestamp: climate.lastTimestamp,
            }),
        [
            climate.sensors,
            climate.connected,
            climate.lastTimestamp,
        ],
    );

    return {
        variables,
        groups: groupVariables(variables),
        connected: climate.connected,
        climateConnected: climate.connected,
        loading: !climate.module,
        total: variables.length,
    };
}

function toSynopticVariables({
    sensors,
    group,
    connected,
    fallbackTimestamp,
}: {
    sensors: ModuleSensorResponse[];
    group: SynopticVariableGroup;
    connected: boolean;
    fallbackTimestamp: string | null;
}): SynopticVariable[] {
    return sensors.map((sensor) => {
        const visual = getVariableVisual(sensor, group);

        return {
            id: `${group}:${sensor.sensorId ?? sensor.key}`,
            sensorId: String(sensor.sensorId ?? sensor.key),
            key: sensor.key,
            group,
            label: sensor.name || sensor.key,
            value: normalizeValue(sensor.value),
            unit: sensor.unit ?? "",
            timestamp: sensor.timestamp ?? fallbackTimestamp ?? undefined,
            connected,
            icon: visual.icon,
            color: visual.color,
        };
    });
}

function groupVariables(variables: SynopticVariable[]) {
    return variables.reduce<Record<SynopticVariableGroup, SynopticVariable[]>>(
        (acc, variable) => {
            acc[variable.group].push(variable);
            return acc;
        },
        {
            Clima: [],
            Rega: [],
        },
    );
}

function normalizeValue(value: unknown): string | number | boolean | null {
    if (
        typeof value === "string" ||
        typeof value === "number" ||
        typeof value === "boolean" ||
        value === null
    ) {
        return value;
    }

    return null;
}

function getVariableVisual(
    sensor: ModuleSensorResponse,
    group: SynopticVariableGroup,
): {
    icon: LucideIcon;
    color: string;
} {
    const text = normalizeText(`${sensor.key} ${sensor.name} ${sensor.unit ?? ""}`);

    if (
        text.includes("temperatura") ||
        text.includes("temperature")
    ) {
        return {
            icon: Thermometer,
            color: "#4FD1C5",
        };
    }

    if (
        text.includes("humidade") ||
        text.includes("humidity")
    ) {
        return {
            icon: Droplet,
            color: "#38BDF8",
        };
    }

    if (
        text.includes("vento") ||
        text.includes("wind")
    ) {
        return {
            icon: Wind,
            color: "#22D3EE",
        };
    }

    if (
        text.includes("radiacao") ||
        text.includes("radiação") ||
        text.includes("radiation")
    ) {
        return {
            icon: Lightbulb,
            color: "#FACC15",
        };
    }

    if (
        text.includes("pressao") ||
        text.includes("pressão") ||
        text.includes("pressure")
    ) {
        return {
            icon: Gauge,
            color: "#38BDF8",
        };
    }

    if (
        text.includes("nivel") ||
        text.includes("nível") ||
        text.includes("level")
    ) {
        return {
            icon: Layers3,
            color: "#0EA5E9",
        };
    }

    if (group === "Clima") {
        return {
            icon: Home,
            color: "#22C55E",
        };
    }

    return {
        icon: Gauge,
        color: "#A3E635",
    };
}

function normalizeText(value: string): string {
    return value
        .toLowerCase()
        .normalize("NFD")
        .replace(/\p{Diacritic}/gu, "");
}