/**
 * Root component. Smoke-tests the full hexagonal pipeline by calling `health`
 * through the {@link SystemGateway} (never `invoke()` directly) and listening
 * for relayed domain events.
 */

import { useEffect, useState } from "react";

import type { DomainEvent, HealthReport } from "@/domain";
import { ProjectsView } from "@/features/projects";
import { FirstRunWizard } from "@/features/first-run";
import { AnnouncementsProvider } from "@/features/announcements";
import { AppExitConfirmDialog } from "@/features/appExit";
import { PluginRuntimeProvider } from "@/features/plugins";
import { Panel, Spinner, Toolbar } from "@/shared";
import { useGateways, shouldUseMock } from "./di";

export function App() {
  const { system, profile } = useGateways();
  const [health, setHealth] = useState<HealthReport | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [events, setEvents] = useState<DomainEvent[]>([]);
  // First-run gating: null while loading, then true (wizard) / false (normal).
  const [firstRun, setFirstRun] = useState<boolean | null>(null);

  useEffect(() => {
    let unsub: (() => void) | undefined;
    let cancelled = false;

    system
      .onDomainEvent((e) => setEvents((prev) => [...prev, e]))
      .then((u) => {
        if (cancelled) u();
        else unsub = u;
      })
      .catch(() => {
        /* event relay unavailable in this environment; ignore for smoke test */
      });

    system
      .health("ui-boot")
      .then((report) => setHealth(report))
      .catch((e: unknown) => setError(describeError(e)));

    return () => {
      cancelled = true;
      unsub?.();
    };
  }, [system]);

  useEffect(() => {
    let cancelled = false;
    profile
      .firstRunState()
      .then((s) => {
        if (!cancelled) setFirstRun(s.isFirstRun);
      })
      .catch(() => {
        // First-run state unavailable: behave as a normal (non-first) run.
        if (!cancelled) setFirstRun(false);
      });
    return () => {
      cancelled = true;
    };
  }, [profile]);

  return (
    <AnnouncementsProvider>
    <PluginRuntimeProvider>
    <div className="flex h-full flex-col bg-canvas text-content">
      {/* ── Header ── */}
      <header className="flex shrink-0 items-center justify-between border-b border-border px-6 py-3">
        <div className="flex items-baseline gap-2">
          <h1 className="text-lg font-semibold tracking-tight">IdeA</h1>
          <span className="rounded-md bg-raised px-1.5 py-0.5 text-[0.65rem] font-medium uppercase text-muted">
            {shouldUseMock() ? "mock" : "tauri"}
          </span>
        </div>
        <Toolbar justify="end">
          <span className="text-xs text-faint">
            {health ? (
              <>
                backend <span className="text-success">●</span> v{health.version} ·{" "}
                {events.length} events
              </>
            ) : error ? (
              <span className="text-danger">backend unavailable</span>
            ) : (
              <span className="inline-flex items-center gap-1.5">
                <Spinner size={12} /> checking…
              </span>
            )}
          </span>
        </Toolbar>
      </header>

      {/* ── Body ── */}
      <div className="flex flex-1 flex-col overflow-hidden">
        {error && (
          <Panel className="mx-4 mt-4 border-danger/40">
            <p className="text-sm text-danger">Error: {error}</p>
          </Panel>
        )}

        {firstRun ? (
          // First launch: the wizard takes over the area, in a scrollable column
          // (it can be taller than the viewport).
          <div className="flex flex-1 justify-center overflow-y-auto p-6">
            <div className="w-full max-w-xl">
              <FirstRunWizard onDone={() => setFirstRun(false)} />
            </div>
          </div>
        ) : (
          // ProjectsView owns the full remaining area (its own IDE layout,
          // single menu bar, and the AI Profiles view switch — ticket #16).
          <ProjectsView />
        )}
      </div>
    </div>
    <AppExitConfirmDialog />
    </PluginRuntimeProvider>
    </AnnouncementsProvider>
  );
}

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