/**
 * #77 lot F1 — the device-name prefill. The contract that matters is the
 * negative one: whatever the UA says, the derived name is something a human
 * would have typed, and never a fragment of the User-Agent itself.
 */
import { describe, it, expect } from "vitest";

import { clampDeviceName, deriveDeviceName } from "./deviceName";

const UA = {
  iphone: "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
  ipad: "Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
  androidChrome:
    "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
  chromeWindows:
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  firefoxLinux: "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0",
  safariMac:
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
  edgeWindows:
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
};

describe("deriveDeviceName", () => {
  it("names phones and tablets by the device, not the browser", () => {
    expect(deriveDeviceName(UA.iphone)).toBe("iPhone");
    expect(deriveDeviceName(UA.ipad)).toBe("iPad");
    expect(deriveDeviceName(UA.androidChrome)).toBe("Android");
  });

  it("names desktops by browser and OS", () => {
    expect(deriveDeviceName(UA.chromeWindows)).toBe("Chrome sur Windows");
    expect(deriveDeviceName(UA.firefoxLinux)).toBe("Firefox sur Linux");
    expect(deriveDeviceName(UA.safariMac)).toBe("Safari sur Mac");
  });

  it("prefers the more specific browser when a UA claims several", () => {
    // Edge's UA also contains "Chrome/" and "Safari/"; naming it "Chrome" would
    // make two different browsers on one machine indistinguishable in the list.
    expect(deriveDeviceName(UA.edgeWindows)).toBe("Edge sur Windows");
  });

  it("falls back to a usable label rather than leaking the UA", () => {
    expect(deriveDeviceName("")).toBe("Cet appareil");
    expect(deriveDeviceName("SomeBot/1.0 (compatible)")).toBe("Cet appareil");
  });

  it("never returns a raw User-Agent fragment", () => {
    for (const ua of Object.values(UA)) {
      const name = deriveDeviceName(ua);
      expect(name).not.toContain("Mozilla");
      expect(name).not.toContain("/");
      expect(name.length).toBeLessThanOrEqual(40);
    }
  });
});

describe("clampDeviceName", () => {
  it("trims and caps at 40 characters", () => {
    expect(clampDeviceName("  iPhone  ")).toBe("iPhone");
    expect(clampDeviceName("x".repeat(60))).toHaveLength(40);
  });
});
