import { defineStore } from "pinia";
import { ref } from "vue";
import { api, type DaemonStatus, type NodeInfo, type SidecarConfig } from "@/lib/api";
import { Events, on } from "@/lib/events";

export type Phase = "idle" | "starting" | "ready" | "error";

export const useNodeStore = defineStore("node", () => {
  const phase = ref<Phase>("idle");
  const status = ref<DaemonStatus | null>(null);
  const info = ref<NodeInfo | null>(null);
  const error = ref<string | null>(null);

  let exitedUnlisten: (() => void) | null = null;
  let readyUnlisten: (() => void) | null = null;

  async function bootstrap() {
    if (!exitedUnlisten) {
      exitedUnlisten = await on<number>(Events.SidecarExited, (e) => {
        error.value = `daemon exited (code ${e.payload})`;
        phase.value = "error";
        status.value = { running: false, apiUrl: null, keyPath: null, configPath: null };
        info.value = null;
      });
    }
    if (!readyUnlisten) {
      readyUnlisten = await on<string>(Events.SidecarReady, async () => {
        await refresh();
      });
    }

    const cur = await api.daemonStatus();
    status.value = cur;
    if (cur.running) {
      phase.value = "ready";
      try {
        info.value = await api.nodeInfo();
      } catch (e) {
        error.value = String(e);
      }
    }
  }

  async function start(config?: SidecarConfig) {
    phase.value = "starting";
    error.value = null;
    try {
      const s = await api.startDaemon(config);
      status.value = s;
      info.value = await api.nodeInfo();
      phase.value = "ready";
    } catch (e) {
      error.value = String(e);
      phase.value = "error";
      throw e;
    }
  }

  async function stop() {
    try {
      const s = await api.stopDaemon();
      status.value = s;
      info.value = null;
      phase.value = "idle";
    } catch (e) {
      error.value = String(e);
      throw e;
    }
  }

  async function refresh() {
    status.value = await api.daemonStatus();
    if (status.value.running) {
      info.value = await api.nodeInfo();
      phase.value = "ready";
    } else {
      info.value = null;
      phase.value = "idle";
    }
  }

  function dispose() {
    exitedUnlisten?.();
    readyUnlisten?.();
    exitedUnlisten = null;
    readyUnlisten = null;
  }

  return {
    phase,
    status,
    info,
    error,
    bootstrap,
    start,
    stop,
    refresh,
    dispose,
  };
});
