import { randomUUID } from "node:crypto";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

import { afterEach, describe, expect, it } from "vitest";

import { MockAmapAdapter } from "../../apps/api/src/amap-adapter.js";
import { createApp } from "../../apps/api/src/app.js";
import { RegistrationService } from "../../apps/api/src/registration.js";
import { MockResendAdapter } from "../../apps/api/src/resend-adapter.js";

const roots: string[] = [];
const registrations: RegistrationService[] = [];

afterEach(() => {
  for (const registration of registrations.splice(0)) registration.close();
  for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true });
});

function createRegistration() {
  const now = Date.parse("2026-08-04T09:00:00.000Z");
  const root = mkdtempSync(join(tmpdir(), "dada-wp7-04-amap-"));
  roots.push(root);
  const registration = new RegistrationService({
    challengePepper: Buffer.alloc(32, 0xa1),
    clock: () => now,
    currentPrivacyNoticeVersion: "p0a-registration-notice-v1",
    databasePath: join(root, "dada.sqlite3"),
    invitePepper: Buffer.alloc(32, 0xa2),
    resend: new MockResendAdapter(),
    sessionPepper: Buffer.alloc(32, 0xa3),
  });
  registrations.push(registration);

  const userId = randomUUID();
  registration.database.prepare(`
    INSERT INTO users (user_id, normalized_email, role, status, counts_toward_stage_limit, registration_id, created_at)
    VALUES (?, ?, 'user', 'active', 1, ?, ?)
  `).run(userId, `${userId}@example.invalid`, randomUUID(), now);
  registration.database.prepare("INSERT INTO user_profiles (user_id, creator_name, social_id) VALUES (?, 'Release Gate User', '@release_gate')").run(userId);
  registration.database.prepare("INSERT INTO credit_accounts (user_id, available_balance, reserved_balance, updated_at) VALUES (?, 10, 0, ?)").run(userId, now);
  return { registration, session: registration.issueAuthenticatedSession(userId, "user") };
}

describe("TDD-WP7-EXT-003 Amap release hard stop", () => {
  it("admits the simulated 1000th request and blocks the 1001st before provider egress", async () => {
    const { registration, session } = createRegistration();
    registration.database.prepare(`
      UPDATE external_service_usage
      SET used_count = 999, service_status = 'active', pause_reason = NULL
      WHERE service_id = 'amap_web_service' AND period_type = 'monthly'
    `).run();

    const amap = new MockAmapAdapter();
    const app = await createApp({ amap, browserGate: false, networkBoundary: { allowTestPort: true }, registration });
    const headers = {
      cookie: `dada_session=${session.sessionToken}`,
      host: "127.0.0.1:43121",
      origin: "http://127.0.0.1:43121",
      "x-csrf-token": registration.issueUserCsrfToken(session.sessionToken),
    };

    const thousandth = await app.inject({
      headers,
      method: "POST",
      payload: { latitude: 0, longitude: 0 },
      url: "/api/v1/location/reverse-geocode",
    });
    const thousandAndFirst = await app.inject({
      headers,
      method: "POST",
      payload: { latitude: 0, longitude: 0 },
      url: "/api/v1/location/reverse-geocode",
    });

    expect(thousandth.statusCode).toBe(200);
    expect(thousandAndFirst.statusCode).toBe(503);
    expect(amap.calls).toHaveLength(1);
    expect(registration.serviceUsage.read("amap_web_service")).toEqual([
      expect.objectContaining({ hardLimit: 1_000, status: "paused_quota", usedCount: 1_000 }),
    ]);
    await app.close();
  });
});
