import { AppNode, nodeLabel, useEnv, useMessages, useProjectId, useStateStore } from "@/lib/state";
import { Button } from "./ui/button";
import { useCallback, useEffect, useState } from "react";
import { generateDodoConfig } from "@/lib/config";
import { useNodes, useReactFlow } from "@xyflow/react";
import { useToast } from "@/hooks/use-toast";

function toNodeType(t: string): string {
    if (t === "ingress") {
        return "gateway-https";
    } else if (t === "service") {
        return "app";
    } else {
        return t;
    }
}

export function Actions() {
    const { toast } = useToast();
    const store = useStateStore();
    const projectId = useProjectId();
    const nodes = useNodes<AppNode>();
    const env = useEnv();
    const messages = useMessages();
    const instance = useReactFlow();
    const [ok, setOk] = useState(false);
    const [loading, setLoading] = useState(false);
    useEffect(() => {
        setOk(!messages.some((m) => m.type === "FATAL"));
    }, [messages, setOk]);
    const monitor = useCallback(async () => {
        const m = async function () {
            const resp = await fetch(`/api/project/${projectId}/status`, {
                method: "GET",
                headers: {
                    "Content-Type": "application/json",
                },
            })
            if (resp.status !== 200) {
                return;
            }
            const data: { type: string, name: string, status: string }[] = await resp.json();
            console.log(data);
            for (const n of nodes) {
                if (n.type === "network") {
                    continue;
                }
                const d = data.find((d) => n.type === toNodeType(d.type) && nodeLabel(n) === d.name);
                if (d !== undefined) {
                    store.updateNodeData(n.id, {
                        state: d?.status,
                    });
                }
            }
            if (data.find((d) => d.status !== "success" && d.status != "failure") !== undefined) {
                setTimeout(m, 1000);
            }
        };
        setTimeout(m, 100);
    }, [projectId, nodes, store]);
    const deploy = useCallback(async () => {
        if (projectId == null) {
            return;
        }
        setLoading(true);
        try {
            const config = generateDodoConfig(nodes, env);
            if (config == null) {
                throw new Error("MUST NOT REACH!");
            }
            const resp = await fetch(`/api/project/${projectId}/deploy`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                },
                body: JSON.stringify({
                    state: JSON.stringify(instance.toObject()),
                    config,
                }),
            });
            if (resp.ok) {
                toast({
                    title: "Deployment succeeded",
                });
                monitor();
            } else {
                toast({
                    variant: "destructive",
                    title: "Deployment failed",
                    description: await resp.text(),
                });
            }
        } catch (e) {
            console.log(e);
            toast({
                variant: "destructive",
                title: "Deployment failed",
            });
        } finally {
            setLoading(false);
        }
    }, [projectId, instance, nodes, env, setLoading, toast, monitor]);
    const save = useCallback(async () => {
        if (projectId == null) {
            return;
        }
        const resp = await fetch(`/api/project/${projectId}/saved`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify(instance.toObject()),
        });
        if (resp.ok) {
            toast({
                title: "Save succeeded",
            });
        } else {
            toast({
                variant: "destructive",
                title: "Save failed",
                description: await resp.text(),
            });
        }
    }, [projectId, instance, toast]);
    const restoreSaved = useCallback(async () => {
        if (projectId == null) {
            return;
        }
        const resp = await fetch(`/api/project/${projectId}/saved`, {
            method: "GET",
        });
        const inst = await resp.json();
        const { x = 0, y = 0, zoom = 1 } = inst.viewport;
        store.setNodes(inst.nodes || []);
        store.setEdges(inst.edges || []);
        instance.setViewport({ x, y, zoom });
    }, [projectId, instance, store]);
    const clear = useCallback(() => {
        store.setEdges([]);
        store.setNodes([]);
        instance.setViewport({ x: 0, y: 0, zoom: 1 });
    }, [store, instance]);
    // TODO(gio): Update store
    const deleteProject = useCallback(async () => {
        if (projectId == null) {
            return;
        }
        const resp = await fetch(`/api/project/${projectId}`, {
            method: "DELETE",
        });
        if (resp.ok) {
            clear();
            store.setProject(undefined);
            toast({
                title: "Save succeeded",
            });
        } else {
            toast({
                variant: "destructive",
                title: "Save failed",
                description: await resp.text(),
            });
        }
    }, [store, clear, projectId, toast]);
    const [props, setProps] = useState({});
    useEffect(() => {
        if (loading) {
            setProps({ loading: true });
        } else if (ok) {
            setProps({ disabled: false });
        } else {
            setProps({ disabled: true });
        }
    }, [ok, loading, setProps]);
    return (
        <>
            <Button onClick={deploy} {...props}>Deploy</Button>
            <Button onClick={save}>Save</Button>
            <Button onClick={restoreSaved}>Restore</Button>
            <Button onClick={clear} variant="destructive">Clear</Button>
            <Button onClick={deleteProject} variant="destructive" disabled={projectId === undefined}>Delete</Button>
        </>
    )
}
