/**
 * `ViewWindow` — the panel-only entry (ticket #23, reworked in #47).
 *
 * A detached OS window loads the same SPA with `?panel=<panel>` (no project id);
 * {@link main} routes to this component instead of the full {@link App} when a
 * `panel` param is present. It re-instantiates the DI (same adapters/gateways as
 * the main window — views are gateway/read-model-driven, so no heavy state is
 * transferred) and renders **only** the requested view for the project the main
 * window currently has in focus.
 *
 * Focus, not embedding (#47): the window never carries — nor reopens — a project
 * id. It reads the current focus from the {@link FocusedProjectGateway} at mount
 * and then tracks {@link FocusedProjectGateway.onFocusedProjectChanged}. While no
 * project is focused it mounts **no** project-scoped panel and shows an "open a
 * project" shell, so a window restored at restart never surfaces a stale
 * project's data.
 *
 * Pure presentation over the ports: no `invoke()`, no cross-window messaging,
 * and crucially no `openProject()` — opening a project is the main window's job.
 */

import { useEffect, useState } from "react";

import type { FocusedProject } from "@/ports";
import { Panel } from "@/shared";
import { PANEL_TITLE, type PanelId } from "@/features/projects";
import { ViewPanelBody, type ViewPanelId } from "@/features/projects";
import { useGateways } from "./di";

/** Panels that may be shown in a detached window (everything but "projects"). */
const DETACHABLE = new Set<string>(
  (Object.keys(PANEL_TITLE) as PanelId[]).filter((p) => p !== "projects"),
);

/** Parsed `?panel=` params, or `null` when absent/invalid. */
export interface ViewWindowParams {
  panel: ViewPanelId;
}

/** Reads and validates the panel-only param from a query string (#47: no project). */
export function parseViewWindowParams(
  search: string,
): ViewWindowParams | null {
  const params = new URLSearchParams(search);
  const panel = params.get("panel");
  if (!panel || !DETACHABLE.has(panel)) return null;
  return { panel: panel as ViewPanelId };
}

export interface ViewWindowProps {
  panel: ViewPanelId;
}

export function ViewWindow({ panel }: ViewWindowProps) {
  const { focusedProject } = useGateways();
  // The focused project this window follows. `undefined` = not yet resolved
  // (initial read in flight); `null` = resolved, no project focused.
  const [focus, setFocus] = useState<FocusedProject | null | undefined>(
    undefined,
  );

  // Read the current focus at mount, then track changes. Never opens a project:
  // the window is a pure follower of the main window's focus (#47).
  useEffect(() => {
    let cancelled = false;
    let unsubscribe: (() => void) | undefined;
    focusedProject
      .getFocusedProject()
      .then((project) => {
        if (!cancelled) setFocus(project);
      })
      .catch(() => {
        if (!cancelled) setFocus(null);
      });
    void focusedProject
      .onFocusedProjectChanged((project) => {
        if (!cancelled) setFocus(project);
      })
      .then((un) => {
        if (cancelled) un();
        else unsubscribe = un;
      });
    return () => {
      cancelled = true;
      unsubscribe?.();
    };
  }, [focusedProject]);

  return (
    <div className="flex h-full flex-col bg-canvas text-content">
      <header className="flex shrink-0 items-center gap-2 border-b border-border px-4 py-2.5">
        <h1 className="text-sm font-semibold text-content">
          {PANEL_TITLE[panel]}
        </h1>
        {focus && (
          <span className="truncate text-xs text-muted">· {focus.name}</span>
        )}
      </header>
      <main className="min-h-0 flex-1 overflow-auto p-4">
        {focus ? (
          // Only mount a project-scoped panel when a project is actually focused
          // — the panels require a real `projectRoot`, never a placeholder.
          <ViewPanelBody
            panel={panel}
            projectId={focus.id}
            projectRoot={focus.root}
          />
        ) : (
          <Panel>
            <p className="text-sm text-muted">
              Ouvrez un projet dans la fenêtre principale pour afficher ce
              panneau.
            </p>
          </Panel>
        )}
      </main>
    </div>
  );
}
