/**
 * Tauri adapter for {@link WindowGateway} (ticket #23). Detaches a View into its
 * own OS window by delegating to the backend's window-lifecycle commands. Like
 * the sibling adapters, this is the only layer allowed to touch
 * `@tauri-apps/api`; components reach it exclusively through the port.
 *
 * Command/event names and payloads below mirror the backend contract owned by
 * DevBackend (build-verified). The backend exposes a single lifecycle channel
 * `view-window://lifecycle`; this adapter narrows it to the port's close-only
 * `onViewWindowClosed` by filtering on `kind === "closed"`.
 */

import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";

import type { Unsubscribe } from "@/domain";
import type {
  ViewWindowClosed,
  ViewWindowSnapshot,
  WindowGateway,
} from "@/ports";

/** The single Tauri event carrying detached-window lifecycle transitions. */
const VIEW_WINDOW_LIFECYCLE = "view-window://lifecycle";

/**
 * Backend lifecycle payload (discriminated on `kind`). Ticket #47 dropped the
 * `projectId` field — a detached window is panel-only and follows the focused
 * project, so lifecycle events carry only `panel` + `label`.
 */
interface ViewWindowLifecycle {
  kind: "opened" | "focused" | "closed";
  panel: string;
  label: string;
}

export class TauriWindowGateway implements WindowGateway {
  async openViewWindow(panel: string): Promise<void> {
    // Panel-only window (#47): no project id — the window follows the focused
    // project published on `focused-project://changed`.
    await invoke("open_view_window", { panel });
  }

  async closeViewWindow(panel: string): Promise<void> {
    await invoke("close_view_window", { panel });
  }

  async listOpenViewWindows(): Promise<ViewWindowSnapshot[]> {
    // Backend serialises the snapshots in camelCase (panel/label/visible), so the
    // wire shape matches the port type directly.
    return invoke<ViewWindowSnapshot[]>("list_open_view_windows");
  }

  async onViewWindowClosed(
    handler: (event: ViewWindowClosed) => void,
  ): Promise<Unsubscribe> {
    // One backend channel for opened/focused/closed; the port only surfaces the
    // close, so drop the other transitions and forward `{ panel }`.
    const unlisten = await listen<ViewWindowLifecycle>(
      VIEW_WINDOW_LIFECYCLE,
      (e) => {
        if (e.payload.kind !== "closed") return;
        handler({ panel: e.payload.panel });
      },
    );
    return unlisten;
  }
}
