/**
 * Ticket #68 — "Desktop only" is a code/test guard, not just a claim.
 *
 * The web client never mounts `ProjectsView` (it routes through `features/web`),
 * so the Deployment surface is unreachable there *today*. This pins that: the
 * web feature must not import the settings surface, and the web transport must
 * refuse the embedded-server port rather than reach for Tauri (absent on web).
 */

import { describe, it, expect } from "vitest";
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";

import { WebDesktopServerGateway } from "@/adapters/http/unsupported";
import type { GatewayError } from "@/domain";

const WEB_FEATURE_DIR = join(process.cwd(), "src", "features", "web");

function collectSourceFiles(dir: string, out: string[] = []): string[] {
  for (const entry of readdirSync(dir)) {
    const full = join(dir, entry);
    if (statSync(full).isDirectory()) collectSourceFiles(full, out);
    else if (/\.tsx?$/.test(entry)) out.push(full);
  }
  return out;
}

describe("the Deployment surface is desktop-only", () => {
  it("features/web does not import the settings surface", () => {
    const offenders = collectSourceFiles(WEB_FEATURE_DIR).filter((file) =>
      /@\/features\/settings/.test(readFileSync(file, "utf8")),
    );
    expect(offenders, `offending files: ${offenders.join(", ")}`).toEqual([]);
  });

  it("the web transport refuses the embedded-server port", async () => {
    const gateway = new WebDesktopServerGateway();

    // Every real operation fails explicitly, with a stable code the UI can branch on.
    for (const call of [
      () => gateway.getExposureSettings(),
      () => gateway.status(),
      () => gateway.start(),
      () => gateway.stop(),
      () =>
        gateway.saveExposureSettings({
          mode: "localOnly",
          autoStart: false,
          port: 0,
          trustedProxies: [],
        }),
      () =>
        gateway.previewExposure({
          mode: "localOnly",
          autoStart: false,
          port: 0,
          trustedProxies: [],
        }),
    ]) {
      const error: Partial<GatewayError> = { code: "UNSUPPORTED_ON_WEB" };
      await expect(call()).rejects.toMatchObject(error);
    }
  });

  it("web status subscription is inert rather than throwing", async () => {
    // Teardown must stay callable: consumers unsubscribe unconditionally.
    const unsubscribe = await new WebDesktopServerGateway().onStatusChanged(() => {
      throw new Error("must never fire on web");
    });
    expect(() => unsubscribe()).not.toThrow();
  });
});
