import React, { useEffect, useState } from "react";
import {fetchInstanceList, sendStartInstanceRequest, sendStopInstanceRequest} from "../api";

type Instance = {
  name: string;
  version: string;
  port: number;
  status: string;
};

export default function InstancesTable() {
  const [instances, setInstances] = useState<Instance[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [actionLoading, setActionLoading] = useState<Record<string, boolean>>({});

  async function refreshInstanceList() {
    setLoading(true);
    setError(null);
    try {
      const data = await fetchInstanceList();
      setInstances(data);
    } catch (e: any) {
      setError(e.message ?? String(e));
      setInstances([]);
    } finally {
      setLoading(false);
    }
  }

  async function waitForStatus(name: string, expectedStatus: string, timeoutMs = 10000, intervalMs = 700) {
    const start = Date.now();
    while (Date.now() - start < timeoutMs) {
      try {
        const list = await fetchInstanceList();
        const inst = list.find(i => i.name === name);
        if (inst?.status === expectedStatus) {
          setInstances(list);
          return inst;
        }
        setInstances(list);
      } catch (e) {
      }
      await new Promise(r => setTimeout(r, intervalMs));
    }
    throw new Error("Timeout waiting for status change");
  }

  async function handleToggle(inst: Instance) {
    setActionLoading(prev => ({ ...prev, [inst.name]: true }));
    try {
      if (inst.status === "STOPPED") {
        await sendStartInstanceRequest(inst.name);
        try {
          await waitForStatus(inst.name, "RUNNING", 15000, 700);
        } catch {
          await refreshInstanceList();
        }
      } else {
        await sendStopInstanceRequest(inst.name);
        try {
          await waitForStatus(inst.name, "STOPPED", 15000, 700);
        } catch {
          await refreshInstanceList();
        }
      }
    } catch (e) {
      console.error(e);
      await refreshInstanceList();
    } finally {
      setActionLoading(prev => ({ ...prev, [inst.name]: false }));
    }
  }

  useEffect(() => {
    refreshInstanceList();
  }, []);

  return (
    <div className="instancesBlock">
      <h3>Instances</h3>

      {error && <div className="error">Error: {error}</div>}

      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Status</th>
            <th>Port</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {!instances && !loading && (
            <tr>
              <td colSpan={4}>No data</td>
            </tr>
          )}

          {instances?.map((inst) => (
            <tr key={`${inst.name}-${inst.port}`}>
              <td>{inst.name}</td>
              <td>
                <span id="statusIndicator" className={inst.status.toLowerCase()}>
                  &#x25E6;{inst.status}
                </span>
              </td>
              <td>{inst.port}</td>
              <td>
                <button
                  id="startStopButton"
                  className={inst.status === "RUNNING" ? "stop" : "start"}
                  onClick={() => void handleToggle(inst)}
                  disabled={loading || actionLoading[inst.name]}
                >
                  {actionLoading[inst.name] ? "..." : inst.status === "RUNNING" ? "\u25FC Stop" : "\u25B6 Start"}
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
