"use client";

import {useEffect, useMemo, useState} from "react";
import {fetchConfig} from "@/app/utils/fetchConfig";
import BusControlTabs from "@/app/components/BusControlTabs";
import MainMix from "@/app/components/MainMix";
import Settings from "@/app/components/Settings";
import {Config} from "@/app/types/config";

// initialize global websocket connection
import {fetchValue, initConnection, isConnected} from "@/app/lib/x32CommunicationManager";


function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {
    return new Promise<T>((resolve, reject) => {
        const timeout = setTimeout(() => {
            reject(new Error("Request timed out"));
        }, timeoutMs);

        promise
            .then((result) => {
                clearTimeout(timeout);
                resolve(result);
            })
            .catch((error) => {
                clearTimeout(timeout);
                reject(error);
            });
    });
}

const Page = () => {
    const [appConfig, setAppConfig] = useState(null);
    const [activeTab, setActiveTab] = useState("mainMix");

    const [webSocketConnected, setWebSocketConnected] = useState(false);
    const [mixerConnected, setMixerConnected] = useState(false);


    useEffect(() => {
        fetchConfig().then((config: Config) => {
            setAppConfig(config);
            initConnection(`ws://${window.location.hostname}:${config.webserver.port}`);
        });
    }, []);

    // periodically check if the websocket connection is still alive
    useEffect(() => {
        const interval = setInterval(() => {
            // wait for appConfig to be fetched
            if (!appConfig) {
                console.log("AppConfig not fetched yet");
                return;
            }
            setWebSocketConnected(isConnected);
            if (!isConnected) {
                console.log("Reconnecting to WebSocket");
                initConnection(`ws://${window.location.hostname}:${appConfig.webserver.port}`);
            } else {
                // check if mixer is connected
                withTimeout(fetchValue("/info"), 1500)
                    .then((response) => {
                        // response is a string starting with "V", which is the API version, if the mixer is connected
                        if (response.startsWith("V")) {
                            setMixerConnected(true);
                        } else {
                            setMixerConnected(false);
                        }
                    })
                    .catch((error) => {
                        console.log("Mixer connection check failed:", error.message);
                        setMixerConnected(false);
                    });

            }
        }, 2000);
        return () => clearInterval(interval);
    }, [appConfig]);


    const tabComponents = useMemo(() => {
            return [
                {
                    id: "mainMix",
                    label: "Main Mix",
                    content: (
                        <MainMix/>
                    ),
                },
                {
                    id: "busControl",
                    label: "Bus Control",
                    content: (
                        <BusControlTabs/>
                    ),
                },
                {
                    id: "recording",
                    label: "Recording",
                    content: (
                        <div>
                            <h2>Recording</h2>
                            <p>Coming soon...</p>
                        </div>
                    ),
                },
                {
                    id: "settings",
                    label: "Settings",
                    content: (
                        <Settings/>
                    ),
                }
            ]
        }
        , []);

    if (!appConfig) {
        return <p>Error fetching config</p>;
    }

    if (!webSocketConnected) {
        return <p>WebSocket not connected</p>;
    }

    if (!mixerConnected) {
        return <p>Mixer not connected</p>;
    }

    return (
        <div>
            <div className="p-4">
                {/* Tabs Header */}
                <div className="flex border-b mb-4">
                    {tabComponents.map((tab) => (
                        <button
                            key={tab.id}
                            className={`px-4 py-2 ${
                                activeTab === tab.id
                                    ? "border-b-2 border-blue-500 text-blue-500"
                                    : "text-gray-500"
                            }`}
                            onClick={() => setActiveTab(tab.id)}
                        >
                            {tab.label}
                        </button>
                    ))}
                </div>

                {/* Tabs Content */}
                <div>
                    {tabComponents.map((tab) => (
                        <div
                            key={tab.id}
                            style={{display: activeTab === tab.id ? "block" : "none"}}
                        >
                            {tab.content}
                        </div>
                    ))}
                </div>
            </div>
        </div>
    );
};

export default Page;