import { afterEach, describe, expect, it } from "vitest";
import { mkdtempSync, rmSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";

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

const resources: Array<{ close: () => Promise<void> | void }> = [];
const roots: string[] = [];
afterEach(async () => {
  for (const resource of resources.splice(0).reverse()) await resource.close();
  for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true });
});

function registrationFixture() {
  const directory = mkdtempSync(join(tmpdir(), "dada-wp4-04-"));
  roots.push(directory);
  const registration = new RegistrationService({
    challengePepper: Buffer.alloc(32, 2), currentPrivacyNoticeVersion: "2026-07-24",
    databasePath: join(directory, "dada.sqlite3"), invitePepper: Buffer.alloc(32, 3), resend: new MockResendAdapter(), sessionPepper: Buffer.alloc(32, 4),
  });
  resources.push({ close: () => registration.close() });
  const userId = "00000000-0000-4000-8000-000000000831";
  registration.database.prepare("INSERT INTO users (user_id, normalized_email, role, status, counts_toward_stage_limit, registration_id, created_at) VALUES (?, 'location@example.invalid', 'user', 'active', 1, ?, ?)").run(userId, crypto.randomUUID(), Date.now());
  registration.database.prepare("INSERT INTO user_profiles (user_id, creator_name, social_id) VALUES (?, 'Location User', '@location')").run(userId);
  registration.database.prepare("INSERT INTO credit_accounts (user_id, available_balance, reserved_balance, updated_at) VALUES (?, 10, 0, ?)").run(userId, Date.now());
  const session = registration.issueAuthenticatedSession(userId, "user");
  return { registration, session };
}

describe("TASK-WP4-04 location adapter API", () => {
  it("requires mutation auth and forwards only coordinates to the local mock adapter", async () => {
    const fixture = registrationFixture();
    const amap = new MockAmapAdapter();
    const app = await createApp({ amap, browserGate: false, registration: fixture.registration });
    resources.push({ close: () => app.close() });
    const csrf = fixture.registration.issueUserCsrfToken(fixture.session.sessionToken);
    const response = await app.inject({
      headers: { cookie: `dada_session=${fixture.session.sessionToken}`, host: "127.0.0.1:43121", origin: "http://127.0.0.1:43121", "x-csrf-token": csrf },
      method: "POST", payload: { latitude: 27.9943, longitude: 120.6994 }, url: "/api/v1/location/reverse-geocode",
    });
    expect(response.statusCode).toBe(200);
    expect(response.json()).toEqual({ formatted_value: "模拟地点 27.9943, 120.6994", service_mode: "mock", status: "resolved" });
    expect(amap.calls).toEqual([{ latitude: 27.9943, longitude: 120.6994 }]);
    const anonymous = await app.inject({ headers: { host: "127.0.0.1:43121", origin: "http://127.0.0.1:43121", "x-csrf-token": "anonymous-csrf-fixture-000000000000000000000000" }, method: "POST", payload: { latitude: 27.9943, longitude: 120.6994 }, url: "/api/v1/location/reverse-geocode" });
    expect(anonymous.statusCode).toBe(401);
    expect(amap.calls).toHaveLength(1);
  });
});
