/**
 * Unit tests for the MDM health-check DB helpers in server/db/mdm.ts.
 *
 * Coverage:
 *   - getLinkedUserDevices
 *   - getMdmEnrollmentStatusesByUdids
 *   - updateUserDeviceMdmHealth
 *
 * All DB calls are mocked via vi.mock("../../server/utils/prisma") and
 * vi.mock("pg").
 */
import { describe, expect, it, vi, beforeEach } from "vitest";
import {
  getLinkedUserDevices,
  getMdmEnrollmentStatusesByUdids,
  updateUserDeviceMdmHealth,
  type MdmEnrollmentStatus,
} from "../../server/db/mdm";

// ─── Prisma mock ─────────────────────────────────────────────────────────────

const mockPrisma = {
  userDevice: {
    findMany: vi.fn(),
    update: vi.fn(),
  },
};

vi.mock("../../server/utils/prisma", () => ({
  usePrisma: () => mockPrisma,
}));

// ─── pg / NanoMDM pool mock ──────────────────────────────────────────────────

const { mockPool } = vi.hoisted(() => {
  const mockPool = {
    query: vi.fn(),
  };
  return { mockPool };
});

vi.mock("pg", () => ({
  __esModule: true,
  default: {
    Pool: vi.fn(() => mockPool),
  },
}));

// ─── Runtime config override ─────────────────────────────────────────────────
// setup.ts stubs useRuntimeConfig, but it does not include mdmDatabaseUrl which
// useMdmPool() requires to build the NanoMDM pg.Pool.

beforeEach(() => {
  const useRuntimeConfig = (globalThis as Record<string, unknown>)
    .useRuntimeConfig as ReturnType<typeof vi.fn>;
  useRuntimeConfig.mockReturnValue({
    public: { supabase: { url: "", key: "" } },
    supabase: { url: "", key: "" },
    mdmDatabaseUrl: "postgres://localhost:5432/nanomdm",
  });
});

// ─── getLinkedUserDevices ────────────────────────────────────────────────────

describe("getLinkedUserDevices", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns an empty array when no linked iOS devices exist", async () => {
    mockPrisma.userDevice.findMany.mockResolvedValue([]);

    const result = await getLinkedUserDevices();

    expect(result).toEqual([]);
    expect(mockPrisma.userDevice.findMany).toHaveBeenCalledTimes(1);
    expect(mockPrisma.userDevice.findMany).toHaveBeenCalledWith({
      where: { platform: "ios", mdmId: { not: null } },
      select: {
        id: true,
        userId: true,
        deviceId: true,
        platform: true,
        mdmId: true,
        mdmEnrolled: true,
        mdmSupervised: true,
        mdmLastSeenAt: true,
      },
    });
  });

  it("returns only iOS devices with mdmId != null and passes the correct where clause", async () => {
    const now = new Date("2026-06-18T00:00:00.000Z");
    const devices = [
      {
        id: "user-device-1",
        userId: "user-1",
        deviceId: "capacitor-id-1",
        platform: "ios",
        mdmId: "udid-1",
        mdmEnrolled: true,
        mdmSupervised: true,
        mdmLastSeenAt: now,
      },
    ];
    mockPrisma.userDevice.findMany.mockResolvedValue(devices);

    const result = await getLinkedUserDevices();

    expect(result).toEqual(devices);
    expect(mockPrisma.userDevice.findMany).toHaveBeenCalledTimes(1);
    expect(mockPrisma.userDevice.findMany).toHaveBeenCalledWith({
      where: { platform: "ios", mdmId: { not: null } },
      select: {
        id: true,
        userId: true,
        deviceId: true,
        platform: true,
        mdmId: true,
        mdmEnrolled: true,
        mdmSupervised: true,
        mdmLastSeenAt: true,
      },
    });
  });

  it("returns multiple linked iOS devices when present", async () => {
    const t1 = new Date("2026-06-17T10:00:00.000Z");
    const t2 = new Date("2026-06-17T11:00:00.000Z");
    const devices = [
      {
        id: "user-device-1",
        userId: "user-1",
        deviceId: "capacitor-id-1",
        platform: "ios",
        mdmId: "udid-1",
        mdmEnrolled: true,
        mdmSupervised: true,
        mdmLastSeenAt: t1,
      },
      {
        id: "user-device-2",
        userId: "user-2",
        deviceId: "capacitor-id-2",
        platform: "ios",
        mdmId: "udid-2",
        mdmEnrolled: false,
        mdmSupervised: false,
        mdmLastSeenAt: t2,
      },
    ];
    mockPrisma.userDevice.findMany.mockResolvedValue(devices);

    const result = await getLinkedUserDevices();

    expect(result).toEqual(devices);
    expect(result).toHaveLength(2);
    expect(mockPrisma.userDevice.findMany).toHaveBeenCalledTimes(1);
  });
});

// ─── getMdmEnrollmentStatusesByUdids ─────────────────────────────────────────

describe("getMdmEnrollmentStatusesByUdids", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns an empty map without querying the pool when given an empty array", async () => {
    const result = await getMdmEnrollmentStatusesByUdids([]);

    expect(result).toEqual(new Map());
    expect(mockPool.query).not.toHaveBeenCalled();
  });

  it("maps NanoMDM rows to Map<string, MdmEnrollmentStatus> correctly", async () => {
    const lastSeenAt = new Date("2026-06-17T12:34:56.000Z");
    mockPool.query.mockResolvedValue({
      rows: [
        {
          udid: "udid-enrolled",
          enrolled: true,
          supervised: true,
          last_seen_at: lastSeenAt,
        },
        {
          udid: "udid-not-enrolled",
          enrolled: false,
          supervised: false,
          last_seen_at: null,
        },
      ],
    });

    const result = await getMdmEnrollmentStatusesByUdids([
      "udid-enrolled",
      "udid-not-enrolled",
    ]);

    expect(result).toEqual(
      new Map<string, MdmEnrollmentStatus>([
        [
          "udid-enrolled",
          { enrolled: true, supervised: true, lastSeenAt: lastSeenAt },
        ],
        [
          "udid-not-enrolled",
          { enrolled: false, supervised: false, lastSeenAt: null },
        ],
      ]),
    );
    expect(mockPool.query).toHaveBeenCalledTimes(1);
    const [actualQuery, actualParams] = mockPool.query.mock.calls[0];
    expect(actualQuery).toContain(
      "LEFT JOIN enrollments e ON e.device_id = d.id",
    );
    expect(actualQuery).toContain(
      "COALESCE(e.enabled = TRUE, FALSE) AS enrolled",
    );
    expect(actualQuery).toContain("(d.unlock_token IS NOT NULL) AS supervised");
    expect(actualQuery).toContain("WHERE d.id = ANY($1::text[])");
    expect(actualParams).toEqual([["udid-enrolled", "udid-not-enrolled"]]);
  });

  it("omits UDIDs that are missing from NanoMDM", async () => {
    mockPool.query.mockResolvedValue({
      rows: [
        {
          udid: "udid-present",
          enrolled: true,
          supervised: true,
          last_seen_at: null,
        },
      ],
    });

    const result = await getMdmEnrollmentStatusesByUdids([
      "udid-present",
      "udid-missing",
    ]);

    expect(result).toEqual(
      new Map<string, MdmEnrollmentStatus>([
        [
          "udid-present",
          { enrolled: true, supervised: true, lastSeenAt: null },
        ],
      ]),
    );
    expect(result.has("udid-missing")).toBe(false);
    expect(mockPool.query).toHaveBeenCalledTimes(1);
  });
});

// ─── updateUserDeviceMdmHealth ───────────────────────────────────────────────

describe("updateUserDeviceMdmHealth", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("calls prisma.userDevice.update with the correct where and data", async () => {
    mockPrisma.userDevice.update.mockResolvedValue({ id: "user-device-1" });

    const status: MdmEnrollmentStatus = {
      enrolled: true,
      supervised: false,
      lastSeenAt: null,
    };

    await updateUserDeviceMdmHealth("user-device-1", status);

    expect(mockPrisma.userDevice.update).toHaveBeenCalledTimes(1);
    expect(mockPrisma.userDevice.update).toHaveBeenCalledWith({
      where: { id: "user-device-1" },
      data: {
        mdmEnrolled: true,
        mdmSupervised: false,
        mdmLastSeenAt: null,
      },
    });
  });

  it("persists a truthy lastSeenAt and supervised flag", async () => {
    mockPrisma.userDevice.update.mockResolvedValue({ id: "user-device-2" });
    const lastSeenAt = new Date("2026-06-17T12:34:56.000Z");

    await updateUserDeviceMdmHealth("user-device-2", {
      enrolled: true,
      supervised: true,
      lastSeenAt,
    });

    expect(mockPrisma.userDevice.update).toHaveBeenCalledWith({
      where: { id: "user-device-2" },
      data: {
        mdmEnrolled: true,
        mdmSupervised: true,
        mdmLastSeenAt: lastSeenAt,
      },
    });
  });
});
