// Unit tests for server/src/localdb/platform.ts (PG Task 1 of the bundled
// PostgreSQL milestone). Pure functions, no DB, no I/O — same style as
// tests/server/amountWords.test.ts.
//
// The point of these is that every platform is asserted from whatever machine
// runs the suite. Nobody has a Mac yet (docs/todo/2026-08-05-install-and-macos.md),
// so "we resolve darwin-arm64 correctly" has to be provable without one.

import { describe, it, expect } from "vitest";
import {
  resolvePlatform,
  isPlatformId,
  PLATFORM_IDS,
  type PlatformId,
} from "../../server/src/localdb/platform.js";

describe("resolvePlatform", () => {
  it.each<[string, string, PlatformId]>([
    ["win32", "x64", "win32-x64"],
    ["darwin", "arm64", "darwin-arm64"],
    ["darwin", "x64", "darwin-x64"],
  ])("%s/%s -> %s", (platform, arch, expected) => {
    const result = resolvePlatform(platform, arch);
    expect(result.ok).toBe(true);
    if (result.ok) expect(result.platform).toBe(expected);
  });

  it("refuses Linux by name, as an unsupported OS rather than a crash", () => {
    const result = resolvePlatform("linux", "x64");
    expect(result.ok).toBe(false);
    if (result.ok) return;
    expect(result.reason).toBe("unsupported-os");
    expect(result.message).toContain("Linux");
    // The alternative has to be in the message: a Linux user with a PostgreSQL
    // of their own is one env var away from a working app, and telling them so
    // is the difference between "unsupported" and "useless".
    expect(result.message).toContain("DATABASE_URL");
  });

  it("echoes a platform it has never heard of verbatim rather than inventing a name for it", () => {
    const result = resolvePlatform("freebsd", "x64");
    expect(result.ok).toBe(false);
    if (result.ok) return;
    expect(result.reason).toBe("unsupported-os");
    expect(result.message).toContain("freebsd");
    expect(result.nodePlatform).toBe("freebsd");
    expect(result.nodeArch).toBe("x64");
  });

  it("distinguishes a supported OS on an unsupported chip from an unsupported OS", () => {
    // Windows on ARM: we ship for Windows, just not for that chip. Reporting it
    // as unsupported-os would send the user looking for a Windows build that
    // already exists.
    const winArm = resolvePlatform("win32", "arm64");
    expect(winArm.ok).toBe(false);
    if (!winArm.ok) {
      expect(winArm.reason).toBe("unsupported-arch");
      expect(winArm.message).toContain("Windows");
      expect(winArm.message).toContain("arm64");
    }

    const win32bit = resolvePlatform("win32", "ia32");
    expect(win32bit.ok).toBe(false);
    if (!win32bit.ok) expect(win32bit.reason).toBe("unsupported-arch");

    const macPpc = resolvePlatform("darwin", "ppc64");
    expect(macPpc.ok).toBe(false);
    if (!macPpc.ok) {
      expect(macPpc.reason).toBe("unsupported-arch");
      expect(macPpc.message).toContain("ppc64");
    }
  });

  it("never throws — every failure is a value the caller can render", () => {
    for (const [platform, arch] of [["linux", "x64"], ["", ""], ["sunos", "s390x"]]) {
      expect(() => resolvePlatform(platform!, arch!)).not.toThrow();
      expect(resolvePlatform(platform!, arch!).ok).toBe(false);
    }
  });

  it("resolves this actual machine to something, or explains why not", () => {
    // Not asserting WHICH platform — the suite has to pass on the owner's
    // Windows box and (eventually) on a Mac. Asserting only that the real
    // process.platform/process.arch pair is handled, not fallen through.
    const result = resolvePlatform(process.platform, process.arch);
    if (result.ok) {
      expect(PLATFORM_IDS).toContain(result.platform);
    } else {
      expect(result.message.length).toBeGreaterThan(0);
    }
  });
});

describe("isPlatformId", () => {
  it("accepts exactly the published ids", () => {
    for (const id of PLATFORM_IDS) expect(isPlatformId(id)).toBe(true);
  });

  it("rejects near-misses and non-strings — this guards instance.json parsing", () => {
    expect(isPlatformId("win32")).toBe(false);
    expect(isPlatformId("win32-X64")).toBe(false);
    expect(isPlatformId("linux-x64")).toBe(false);
    expect(isPlatformId("")).toBe(false);
    expect(isPlatformId(null)).toBe(false);
    expect(isPlatformId(undefined)).toBe(false);
    expect(isPlatformId(42)).toBe(false);
    expect(isPlatformId({ toString: () => "win32-x64" })).toBe(false);
  });
});
