"use client";

import { Fragment, useEffect, useRef, useState } from "react";

interface InfraServer {
    tier_name: string;
    tenant: Tenant[] | null;
    server: Server;
    database: Database;
}

interface Tenant {
    name: string;
}

interface Server {
    name: string;
    host: string;
    port: number;
    ws: string
}

interface Database {
    host: string;
    port: number;
    username: string;
    password: string;
}

interface ServerStatus {
    cpu_usage: number;
    database: DatabaseStatus;
    disk_usage: number;
    health: string;
    latency_ms: number;
    memory_usage: number;
    network_rx_bytes: string;
    network_tx_bytes: string;
    running_containers: number;
    status: string;
    unhealthy_containers: number;
    uptime_seconds: string;
}

interface DatabaseStatus {
    status: string;
    latency_ms: number;
    active_connection: number;
    database_size: string;
    checked_at: string;
}

interface ServerStatusMap {
    [tierName: string]: ServerStatus;
}
export default function ServerStatusWidget() {
    const [data, setData] = useState<InfraServer[]>([]);
    const [serverStatus, setServerStatus] = useState<ServerStatusMap>({});

    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    const socketsRef = useRef<Record<string, WebSocket>>({});

    useEffect(() => {
        const loadServers = async () => {
            try {
                setLoading(true);
                setError(null);

                const response = await fetch("/api/infrastructure/server",
                    {
                        method: "GET",
                        headers: {
                            "Content-Type":
                                "application/json",
                        },
                    }
                );

                if (!response.ok) {
                    throw new Error(`Failed to fetch server infrastructure (${response.status})`);
                }

                const result = await response.json();
                const tiers: InfraServer[] = result.data ?? [];
                setData(tiers);

                tiers.forEach((tier) => {
                    if (!tier.server || !tier.server.host || !tier.server.port) {
                        return;
                    }

                    connectWebSocket(tier);
                });
            } catch (err) {
                console.log("Failed to load server infrastructure:", err);

                setError(err instanceof Error ? err.message : "Failed to load server infrastructure");
            } finally {
                setLoading(false);
            }
        };

        loadServers();

        return () => {
            Object.values(socketsRef.current).forEach((socket) => {
                socket.close();
            });

            socketsRef.current = {};
        };
    }, []);

    const connectWebSocket = (tier: InfraServer) => {
        if (socketsRef.current[tier.tier_name]) {
            return;
        }

        const wsUrl = tier.server.ws;
        console.log(`[WS] Connecting ${tier.tier_name} -> ${wsUrl}`);

        const socket = new WebSocket(wsUrl);
        socketsRef.current[tier.tier_name] = socket;

        socket.onopen = () => {
            console.log(`[WS] Connected: ${tier.tier_name}`);
            const payload = {
                action: "subscribe",
                topic: "server_status",
                data: {
                    host: tier.database.host,
                    port: tier.database.port,
                    username: tier.database.username,
                    password: tier.database.password,
                },
            };

            console.log(`[WS] Subscribe ${tier.tier_name}:`, payload);
            socket.send(JSON.stringify(payload));
        };

        socket.onmessage = (event) => {
            try {
                const message = JSON.parse(event.data);
                console.log(`[WS] Message ${tier.tier_name}:`, message);

                if (message.topic !== "server_status") {
                    return;
                }

                const status: ServerStatus = message.data;

                setServerStatus((prev) => ({
                    ...prev,
                    [tier.tier_name]:
                        status,
                }));
            } catch (err) {
                console.log(`[WS] Invalid message ${tier.tier_name}:`, event.data, err);
            }
        };

        socket.onerror = (event) => {
            console.log(`[WS] Error: ${tier.tier_name}`, event);

            setServerStatus((prev) => ({
                ...prev,
                [tier.tier_name]: {
                    ...prev[tier.tier_name],
                    status: "offline",
                    health: "critical",
                } as ServerStatus,
            }));
        };

        socket.onclose = () => {
            console.log(`[WS] Closed: ${tier.tier_name}`);

            delete socketsRef.current[tier.tier_name];
            setServerStatus((prev) => ({
                ...prev,
                [tier.tier_name]: {
                    ...prev[tier.tier_name],
                    status: "offline",
                    health: "critical",
                } as ServerStatus,
            }));
        };
    };

    const getHealthClass = (health?: string) => {
        switch (health?.toLowerCase()) {
            case "healthy":
            case "ok":
                return "text-success";
            case "warning":
            case "degraded":
                return "text-warning";
            case "critical":
            case "unhealthy":
                return "text-danger";
            default:
                return "text-secondary";
        }
    };

    const getHealthBackground = (health?: string) => {
        switch (health?.toLowerCase()) {
            case "healthy":
            case "ok":
                return "bg-green-lt";
            case "warning":
            case "degraded":
                return "bg-yellow-lt";
            case "critical":
            case "unhealthy":
                return "bg-red-lt";
            default:
                return "bg-secondary-lt";
        }
    };

    const getHealthText = (health?: string) => {
        switch (health?.toLowerCase()) {
            case "healthy":
                return "All systems are operating normally."
            case "warning":
                return "System health requires attention."
            case "critical":
                return "Critical issues have been detected."
            default:
                return "Waiting for the system status.";
        }
    };

    const getHealthIcon = (health?: string) => {
        switch (health?.toLowerCase()) {
            case "healthy":
                return "ti ti-check"
            case "warning":
                return "ti ti-alert-triangle"
            case "critical":
                return "ti ti-alert-triangle"
            default:
                return "ti ti-question-mark";
        }
    };

    const getDotClass = (health?: string) => {
        switch (health?.toLowerCase()) {
            case "healthy":
            case "ok":
                return "bg-success";
            case "warning":
            case "degraded":
                return "bg-warning";
            case "critical":
            case "unhealthy":
                return "bg-danger";
            default:
                return "bg-secondary";
        }
    };

    const getProgressClass = (value: number) => {
        if (value >= 90) {
            return "bg-danger";
        }
        if (value >= 75) {
            return "bg-warning";
        }
        return "bg-success";
    };

    const getProgressClassIcon = (value: number) => {
        if (value >= 90) {
            return "bg-danger-lt";
        }
        if (value >= 75) {
            return "bg-warning-lt";
        }
        return "bg-success-lt";
    };

    const formatLatency = (latency?: number) => {
        if (latency === undefined || latency < 0) {
            return "N/A";
        }

        return `${latency} ms`;
    };

    const formatCheckedAt = (checkedAt?: string) => {
        if (!checkedAt) {
            return "-";
        }

        try {
            return new Date(checkedAt).toLocaleString("id-ID", {
                day: "2-digit",
                month: "2-digit",
                year: "numeric",
                hour: "2-digit",
                minute: "2-digit",
                second: "2-digit",
            });
        } catch {
            return checkedAt;
        }
    };

    if (loading) {
        return (
            <div className="row row-cards">
                <div className="col-12">
                    <div className="card">
                        <div className="card-body text-center py-5">
                            <div className="spinner-border text-primary" role="status"/>
                            <div className="text-secondary mt-3">Loading server status...</div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }

    if (error) {
        return (
            <div className="row row-cards">
                <div className="col-12">
                    <div className="alert alert-danger">
                        <div className="d-flex">
                            <i className="ti ti-alert-circle fs-2 me-2" />
                            <div>
                                <h4 className="alert-title">Failed to load server status</h4>
                                <div className="text-secondary">{error}</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
    return (
        <>
        {data.map((tier, index) => {
            const status = serverStatus[tier.tier_name];
            const health = status?.health;
            const isOnline = status?.status === "online";
            const hasStatus = !!status;
            const db = status?.database;
            const dbOnline = db?.status === "online";

            return (
                <Fragment key={index+1}>
                <div className="row align-items-center">
                    <div className="col-auto">
                        <span className="avatar avatar-lg bg-primary-lt">
                            <i className="ti ti-server-2"></i>
                        </span>
                    </div>
                    <div className="col">
                        <div className="h3 mb-1">
                            {tier.server.name || "-"}
                        </div>
                        {tier.tenant && tier.tenant.length > 0 ? (
                            <div>
                                {tier.tenant.map((tenant,index) => (
                                        <span key={`${tier.tier_name}-${index}`} className="badge bg-success-lt me-1 mb-1">
                                            {tenant.name}
                                        </span>
                                    )
                                )}
                            </div>
                        ) : (
                            <span className="text-secondary small">
                                No tenant
                            </span>
                        )}
                    </div>
                </div>
                <div className="col-md-6 col-xl-4">
                    <div className="d-flex justify-content-center align-items-center pt-3">
                        <img src="/static/image/server.png" width="70%" alt="Server"/>
                    </div>
                        <div className="card p-2 m-3">
                        <div className="card-body p-0">
                            <div className="row align-items-center">
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getHealthBackground(health)}`}>
                                        <i className="ti ti-shield-check"></i>
                                    </span>
                                </div>
                                <div className="col">
                                    <div className={`h4 mb-0 ${getHealthClass(health)}`}>
                                        System {hasStatus ? health?.toUpperCase() ?? "Unkown" : "Checking"}
                                    </div>
                                    <h4 className="mb-1">{getHealthText(health)}</h4>
                                </div>
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getHealthBackground(health)}`}>
                                        <i className={getHealthIcon(health)}></i>
                                    </span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="col-md-6 col-xl-8 h-100">
                    <div className="row row-cards mb-3">
                        <div className="col-md-6 col-xl-12">
                            <div className="card h-100 w-100">
                                <div className="card-body">
                                    <div className="row align-items-center">
                                        <div className="col">
                                            <div className="row align-items-center">
                                                <div className="col-auto">
                                                    <span className="avatar avatar-lg bg-primary-lt">
                                                        <i className="ti ti-database"></i>
                                                    </span>
                                                </div>
                                                <div className="col">
                                                    <div className="text-secondary">Database</div>
                                                    <div className={dbOnline ? "fw-bold text-success" : "fw-bold text-danger"}>
                                                        {db?.status?.toUpperCase() ?? "CHECKING"}
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div className="col">
                                            <div className="row align-items-center">
                                                <div className="col-auto">
                                                    <span className="avatar avatar-lg bg-primary-lt">
                                                        <i className="ti ti-heart-rate-monitor"></i>
                                                    </span>
                                                </div>
                                                <div className="col">
                                                    <div className="text-secondary">Health</div>
                                                    <div className={`fw-bold ${getHealthClass(health)}`}>
                                                        {hasStatus ? health?.toUpperCase() ?? "UNKNOWN" : "CHECKING"}
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div className="col">
                                            <div className="row align-items-center">
                                                <div className="col-auto">
                                                    <span className="avatar avatar-lg bg-primary-lt">
                                                        <i className="ti ti-clock"></i>
                                                    </span>
                                                </div>
                                                <div className="col">
                                                    <div className="text-secondary">Uptime</div>
                                                    <div className="fw-bold text-success">
                                                        {status?.uptime_seconds ?? "-"}
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        {/* <div className="col">
                                            ad
                                        </div> */}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div className="card">
                        <div className="card-body">
                            <div className="row align-items-center">
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getProgressClassIcon(status?.cpu_usage ?? 0)}`}>
                                        <i className="ti ti-cpu"></i>
                                    </span>
                                </div>
                                <div className="col">
                                    <div>
                                        <div className="d-flex justify-content-between mb-1">
                                            <small className="text-secondary">CPU Usage</small>
                                            <small className="fw-bold">{status?.cpu_usage ?? "-"} {status && "%"}</small>
                                        </div>
                                        <div className="progress progress-lg">
                                            <div className={`progress-bar ${getProgressClass(status?.cpu_usage ?? 0)}`} style={{width: `${status?.cpu_usage ?? 0}%`}}/>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="row align-items-center mt-3">
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getProgressClassIcon(status?.memory_usage ?? 0)}`}>
                                        <i className="ti ti-device-sd-card"></i>
                                    </span>
                                </div>
                                <div className="col">
                                    <div>
                                        <div className="d-flex justify-content-between mb-1">
                                            <small className="text-secondary">Memory Usage</small>
                                            <small className="fw-bold">{status?.memory_usage ?? "-"} {status && "%"}</small>
                                        </div>
                                        <div className="progress progress-lg">
                                            <div className={`progress-bar ${getProgressClass(status?.memory_usage ?? 0)}`} style={{width: `${status?.memory_usage ?? 0}%`}}/>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="row align-items-center mt-3">
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getProgressClassIcon(status?.disk_usage ?? 0)}`}>
                                        <i className="ti ti-database"></i>
                                    </span>
                                </div>
                                <div className="col">
                                    <div>
                                        <div className="d-flex justify-content-between mb-1">
                                            <small className="text-secondary">Disk Usage</small>
                                            <small className="fw-bold">{status?.disk_usage ?? "-"} {status && "%"}</small>
                                        </div>
                                        <div className="progress progress-lg">
                                            <div className={`progress-bar ${getProgressClass(status?.disk_usage ?? 0)}`} style={{width: `${status?.disk_usage ?? 0}%`}}/>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="row align-items-center mt-3">
                                <div className="col-auto">
                                    <span className={`avatar avatar-lg ${getProgressClassIcon(status?.disk_usage ?? 0)}`}>
                                        <i className="ti ti-network"></i>
                                    </span>
                                </div>
                                <div className="col">
                                    <div className="row">
                                        <div className="col-md-6 col-xl-4">
                                            <h3>{status?.network_rx_bytes ?? "-"}</h3>
                                            <h5>Network RX</h5>
                                        </div>
                                        <div className="col-md-6 col-xl-4">
                                            <h3>{status?.network_tx_bytes ?? "-"}</h3>
                                            <h5>Network TX</h5>
                                        </div>
                                        <div className="col-md-6 col-xl-4">
                                            <h3>{formatLatency(db?.latency_ms)}</h3>
                                            <h5>Database Latency</h5>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                </Fragment>
            );
        })}
        </>
    );
}