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]);
    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]);
    const [st, setSt] = useState<string>();
    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, setSt]);
    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, st]);
    const clear = useCallback(() => {
        store.setEdges([]);
        store.setNodes([]);
        instance.setViewport({ x: 0, y: 0, zoom: 1 });
    }, [store]);
    // 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]);
    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>
        </>
    )
}
