/**
 * View-model hook for the project work-state read-model.
 *
 * It consumes the WorkStateGateway only, and optionally subscribes to existing
 * domain events through SystemGateway to refresh the read-only snapshot.
 */

import { useCallback, useEffect, useState } from "react";

import type { GatewayError, ProjectWorkState } from "@/domain";
import { useGateways } from "@/app/di";

export interface ProjectWorkStateViewModel {
  state: ProjectWorkState | null;
  error: string | null;
  busy: boolean;
  refresh: () => Promise<void>;
}

function describe(e: unknown): string {
  if (e && typeof e === "object" && "message" in e) {
    return String((e as GatewayError).message);
  }
  return String(e);
}

export function useProjectWorkState(projectId: string): ProjectWorkStateViewModel {
  const { workState, system } = useGateways();
  const [state, setState] = useState<ProjectWorkState | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const refresh = useCallback(async () => {
    setBusy(true);
    setError(null);
    try {
      setState(await workState.getProjectWorkState(projectId));
    } catch (e) {
      setError(describe(e));
    } finally {
      setBusy(false);
    }
  }, [projectId, workState]);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  useEffect(() => {
    if (!system) return;
    let unsubscribe: (() => void) | undefined;
    let cancelled = false;
    void system.onDomainEvent((event) => {
      if (
        event.type === "agentLaunched" ||
        event.type === "agentExited" ||
        event.type === "agentBusyChanged" ||
        event.type === "delegationReady" ||
        event.type === "orchestratorRequestProcessed" ||
        event.type === "backgroundTaskChanged" ||
        event.type === "agentInboxChanged" ||
        event.type === "agentWakeChanged"
      ) {
        void refresh();
      }
    }).then((u) => {
      if (cancelled) u();
      else unsubscribe = u;
    });
    return () => {
      cancelled = true;
      unsubscribe?.();
    };
  }, [refresh, system]);

  return { state, error, busy, refresh };
}
