import assert from "node:assert/strict";
import { describe, it } from "node:test";

import type { ElyAnalyticsDataPoint } from "../src/bindings.js";
import { authSessionCacheKvKey, authTokenHash } from "../src/auth.js";
import { handleRequest } from "../src/index.js";
import {
  ACCESS_TOKEN,
  PUBLIC_KEY,
  sessionDocument,
  testD1Database,
  testEnv,
} from "./devices_test_support.js";

const IDEMPOTENCY_KEY = "device-register-0001";

describe("device routes", () => {
  it("returns authenticated user devices from D1", async () => {
    const tokenHash = await authTokenHash(ACCESS_TOKEN);
    const auditEvents: ElyAnalyticsDataPoint[] = [];
    const d1 = testD1Database([
      {
        device_id: "device-01",
        public_key: PUBLIC_KEY,
        device_name: "MacBook Pro",
        platform: "macOS",
        approval_status: "approved",
        created_at: 1_780_000_000,
        approved_at: 1_780_000_010,
        last_active_at: 1_780_000_020,
        revoked_at: null,
      },
      {
        device_id: "device-02",
        public_key: PUBLIC_KEY,
        device_name: "iMac",
        platform: "macOS",
        approval_status: "revoked",
        created_at: 1_770_000_000,
        approved_at: 1_770_000_010,
        last_active_at: 1_770_000_020,
        revoked_at: 1_770_000_030,
      },
    ]);

    const response = await handleRequest(
      new Request("https://elydora.test/api/devices", {
        headers: { authorization: `Bearer ${ACCESS_TOKEN}`, "cf-ray": "ray-devices" },
      }),
      testEnv({
        auditEvents,
        d1,
        kvEntries: [[authSessionCacheKvKey("local", tokenHash), sessionDocument()]],
      }),
    );

    assert.equal(response.status, 200);
    assert.equal(response.headers.get("cache-control"), "no-store");
    assert.deepEqual(await response.json(), {
      version: 1,
      user_id: "user-01",
      devices: [
        {
          device_id: "device-01",
          public_key: PUBLIC_KEY,
          device_name: "MacBook Pro",
          platform: "macOS",
          approval_status: "approved",
          created_at: 1_780_000_000,
          approved_at: 1_780_000_010,
          last_active_at: 1_780_000_020,
          revoked_at: null,
          current: true,
        },
        {
          device_id: "device-02",
          public_key: PUBLIC_KEY,
          device_name: "iMac",
          platform: "macOS",
          approval_status: "revoked",
          created_at: 1_770_000_000,
          approved_at: 1_770_000_010,
          last_active_at: 1_770_000_020,
          revoked_at: 1_770_000_030,
          current: false,
        },
      ],
    });
    assert.deepEqual(d1.binds, [["user-01"]]);
    assert.ok(d1.queries[0]?.includes("FROM user_devices"));
    assert.deepEqual(auditEvents[0]?.blobs?.slice(0, 8), [
      "devices.list",
      "GET",
      "/api/devices",
      "handled",
      "ray-devices",
      "",
      "user-01",
      "device-01",
    ]);
  });

  it("rejects unauthenticated device list requests before D1 reads", async () => {
    const d1 = testD1Database([]);
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices"),
      testEnv({ d1 }),
    );

    assert.equal(response.status, 401);
    assert.deepEqual(await response.json(), { error: "authorization_missing" });
    assert.deepEqual(d1.queries, []);
  });

  it("rejects unsupported device list methods before session reads", async () => {
    const d1 = testD1Database([]);
    const kvReads: string[] = [];
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices", { method: "POST" }),
      testEnv({ d1, kvReads }),
    );

    assert.equal(response.status, 405);
    assert.equal(response.headers.get("allow"), "GET");
    assert.deepEqual(await response.json(), { error: "method_not_allowed" });
    assert.deepEqual(kvReads, []);
    assert.deepEqual(d1.queries, []);
  });

  it("returns a generic server error for malformed D1 device rows", async () => {
    const tokenHash = await authTokenHash(ACCESS_TOKEN);
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices", {
        headers: { authorization: `Bearer ${ACCESS_TOKEN}` },
      }),
      testEnv({
        d1: testD1Database([
          {
            device_id: "device-01",
            public_key: PUBLIC_KEY,
            device_name: "MacBook Pro",
            platform: "macOS",
            approval_status: "deleted",
            created_at: 1_780_000_000,
            approved_at: null,
            last_active_at: null,
            revoked_at: null,
          },
        ]),
        kvEntries: [[authSessionCacheKvKey("local", tokenHash), sessionDocument()]],
      }),
    );

    assert.equal(response.status, 500);
    assert.deepEqual(await response.json(), { error: "devices_invalid" });
  });

  it("registers the current device as a pending idempotent D1 write", async () => {
    const tokenHash = await authTokenHash(ACCESS_TOKEN);
    const d1 = testD1Database([
      {
        device_id: "device-01",
        public_key: PUBLIC_KEY.toUpperCase(),
        device_name: "MacBook Pro",
        platform: "macOS",
        approval_status: "pending",
        created_at: 1_780_000_100,
        approved_at: null,
        last_active_at: 1_780_000_100,
        revoked_at: null,
      },
    ]);

    const response = await handleRequest(
      new Request("https://elydora.test/api/devices/register", {
        method: "POST",
        headers: {
          authorization: `Bearer ${ACCESS_TOKEN}`,
          "content-type": "application/json",
        },
        body: JSON.stringify(deviceRegistrationBody()),
      }),
      testEnv({
        d1,
        kvEntries: [[authSessionCacheKvKey("local", tokenHash), sessionDocument()]],
      }),
    );

    assert.equal(response.status, 201);
    assert.equal(response.headers.get("cache-control"), "no-store");
    assert.deepEqual(await response.json(), {
      version: 1,
      user_id: "user-01",
      device: {
        device_id: "device-01",
        public_key: PUBLIC_KEY,
        device_name: "MacBook Pro",
        platform: "macOS",
        approval_status: "pending",
        created_at: 1_780_000_100,
        approved_at: null,
        last_active_at: 1_780_000_100,
        revoked_at: null,
        current: true,
      },
    });
    assert.ok(d1.queries[0]?.includes("INSERT INTO user_devices"));
    assert.ok(d1.queries[0]?.includes("ON CONFLICT(user_id, idempotency_key) DO NOTHING"));
    assert.ok(d1.queries[1]?.includes("WHERE user_id = ? AND idempotency_key = ?"));
    assert.ok(d1.queries[2]?.includes("better_auth_session_device_context"));
    assert.deepEqual(d1.binds[0]?.slice(0, 5), [
      "user-01",
      "device-01",
      PUBLIC_KEY,
      "MacBook Pro",
      "macOS",
    ]);
    assert.equal(typeof d1.binds[0]?.[5], "number");
    assert.equal(typeof d1.binds[0]?.[6], "number");
    assert.equal(d1.binds[0]?.[7], IDEMPOTENCY_KEY);
    assert.deepEqual(d1.binds[1], ["user-01", IDEMPOTENCY_KEY]);
    assert.deepEqual(d1.binds[2]?.slice(0, 3), ["session-01", "user-01", "device-01"]);
  });

  it("rejects invalid device registration payloads before D1 writes", async () => {
    const tokenHash = await authTokenHash(ACCESS_TOKEN);
    const d1 = testD1Database([]);
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices/register", {
        method: "POST",
        headers: {
          authorization: `Bearer ${ACCESS_TOKEN}`,
          "content-type": "application/json",
        },
        body: JSON.stringify({ ...deviceRegistrationBody(), idempotency_key: "short" }),
      }),
      testEnv({
        d1,
        kvEntries: [[authSessionCacheKvKey("local", tokenHash), sessionDocument()]],
      }),
    );

    assert.equal(response.status, 400);
    assert.deepEqual(await response.json(), { error: "invalid_device_registration" });
    assert.deepEqual(d1.queries, []);
  });

  it("rejects registration for a different authenticated device before D1 writes", async () => {
    const tokenHash = await authTokenHash(ACCESS_TOKEN);
    const d1 = testD1Database([]);
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices/register", {
        method: "POST",
        headers: {
          authorization: `Bearer ${ACCESS_TOKEN}`,
          "content-type": "application/json",
        },
        body: JSON.stringify({ ...deviceRegistrationBody(), device_id: "device-02" }),
      }),
      testEnv({
        d1,
        kvEntries: [[authSessionCacheKvKey("local", tokenHash), sessionDocument()]],
      }),
    );

    assert.equal(response.status, 403);
    assert.deepEqual(await response.json(), { error: "device_context_mismatch" });
    assert.deepEqual(d1.queries, []);
  });

  it("rejects unauthenticated device registration before D1 writes", async () => {
    const d1 = testD1Database([]);
    const response = await handleRequest(
      new Request("https://elydora.test/api/devices/register", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(deviceRegistrationBody()),
      }),
      testEnv({ d1 }),
    );

    assert.equal(response.status, 401);
    assert.deepEqual(await response.json(), { error: "authorization_missing" });
    assert.deepEqual(d1.queries, []);
  });
});

function deviceRegistrationBody(): Record<string, unknown> {
  return {
    version: 1,
    device_id: "device-01",
    public_key: PUBLIC_KEY,
    device_name: "MacBook Pro",
    platform: "macOS",
    idempotency_key: IDEMPOTENCY_KEY,
  };
}
