import Stack from "@/twui/components/layout/Stack";
import { RefObject, useContext, useEffect, useRef, useState } from "react";
import { AppContext } from "@/src/pages/_app";
import {
    NormalizedServerObject,
    ParsedDeploymentServiceConfig,
    ServerTerminalTargets,
    TtydInfoObject,
    WebSocketDataType,
} from "@/src/types";
import useWebSocketEventHandler from "@/twui/components/hooks/useWebSocketEventHandler";
import _ from "lodash";
import Loading from "@/twui/components/elements/Loading";
import Center from "@/twui/components/layout/Center";
import TtydIframe from "@/src/components/general/ttyd-iframe";
import useIntersectionObserver from "@/twui/components/hooks/useIntersectionObserver";
import useStatus from "@/twui/components/hooks/useStatus";

type Props = {
    service: ParsedDeploymentServiceConfig;
    server: NormalizedServerObject;
    target: (typeof ServerTerminalTargets)[number]["name"];
    log_cmd?: string;
    portRef?: RefObject<number | undefined>;
};

export default function ServiceClusterServerViews({
    service,
    server,
    target,
    log_cmd,
    portRef,
}: Props) {
    const { pageProps, ws } = useContext(AppContext);

    const viewRef = useRef<HTMLDivElement>(undefined);

    const { data } = useWebSocketEventHandler<WebSocketDataType>();
    const { isIntersecting } = useIntersectionObserver({
        elementRef: viewRef,
        options: { rootMargin: "-200px", threshold: 0 },
    });

    const [ttyd, setTtyd] = useState<TtydInfoObject>();

    const { refresh, setRefresh } = useStatus();

    const WsReqSentRef = useRef(false);

    function sendKillPort() {
        if (ttyd?.port) {
            ws.sendData({
                event: "client:kill-port",
                server,
                service: _.omit(service, ["servers"]),
                port: ttyd.port,
            });
        }
    }

    useEffect(() => {
        if (!ws?.socket || WsReqSentRef.current || !isIntersecting) {
            return;
        }

        if (target == "logs") {
            ws.sendData({
                event: "client:service-server-logs",
                server,
                service: _.omit(service, ["servers"]),
                cmd: log_cmd,
            });
        } else {
            ws.sendData({
                event: "client:service-server-shell",
                server,
                service: _.omit(service, ["servers"]),
            });
        }

        WsReqSentRef.current = true;

        return function () {
            sendKillPort();
        };
    }, [ws, refresh, isIntersecting]);

    useEffect(() => {
        if (WsReqSentRef.current) {
            sendKillPort();

            setTtyd(undefined);
            WsReqSentRef.current = false;
            setRefresh((prev) => prev + 1);
        }
    }, [target, log_cmd]);

    useEffect(() => {
        if (ttyd) return;

        if (
            data?.event == "server:service-server-logs" &&
            data?.ttyd &&
            data.server?.private_ip == server.private_ip
        ) {
            setTimeout(() => {
                setTtyd(
                    data.ttyd
                        ? {
                              ...data.ttyd,
                              href: `${window.location.origin}${data.ttyd.url}`,
                          }
                        : undefined,
                );
            }, 2000);
        }

        if (
            data?.event == "server:service-server-shell" &&
            data?.ttyd &&
            data.server?.private_ip == server.private_ip
        ) {
            setTimeout(() => {
                setTtyd(
                    data.ttyd
                        ? {
                              ...data.ttyd,
                              href: `${window.location.origin}${data.ttyd.url}`,
                          }
                        : undefined,
                );
            }, 2000);
        }

        if (portRef && data?.ttyd?.port) {
            portRef.current = data.ttyd.port;
        }
    }, [data]);

    useEffect(() => {
        if (!ttyd?.port) return;

        if (isIntersecting) {
            WsReqSentRef.current = false;
            setTtyd(undefined);
        } else {
            sendKillPort();
        }
    }, [isIntersecting]);

    // const dev_logs_url = ttydLogs?.port
    //     ? `http://localhost:${ttydLogs.port}`
    //     : undefined;

    const title = (
        <>
            <code>{server.private_ip}</code> {target}
        </>
    );

    return (
        <Stack className="gap-0 w-full" componentRef={viewRef as any}>
            {isIntersecting && ttyd?.url && ttyd.port ? (
                <Stack className="gap-0">
                    <TtydIframe
                        url={ttyd?.url}
                        title={title}
                        wrapperProps={{
                            className: "border-none",
                        }}
                    />
                </Stack>
            ) : (
                <Center className="p-10 h-[460px]">
                    <Loading />
                </Center>
            )}
            <hr />
        </Stack>
    );
}
