import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";

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

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";
import { registrationNotice } from "../../packages/shared-contracts/src/registration-notice.js";

const roots: string[] = [];
const services: RegistrationService[] = [];
const writeHeaders = { host: "127.0.0.1:43121", origin: "http://127.0.0.1:43121" };

function createHarness() {
  const root = mkdtempSync(join(tmpdir(), "dada-wp1-03-notice-"));
  roots.push(root);
  const resend = new MockResendAdapter();
  const registration = new RegistrationService({
    challengePepper: Buffer.alloc(32, 0x74),
    clock: () => Date.parse("2026-07-28T09:30:00.000Z"),
    codeGenerator: () => "418205",
    currentPrivacyNoticeVersion: registrationNotice.version,
    databasePath: join(root, "dada.sqlite3"),
    inviteCodeGenerator: () => "DADA-WP1-03-NOTICE",
    invitePepper: Buffer.alloc(32, 0x75),
    resend,
    sessionPepper: Buffer.alloc(32, 0x76),
  });
  services.push(registration);
  return { registration, resend };
}

function snapshot(registration: RegistrationService) {
  return {
    consents: registration.database.prepare("SELECT COUNT(*) AS count FROM privacy_consents").get().count,
    credits: registration.database.prepare("SELECT COUNT(*) AS count FROM credit_accounts").get().count,
    invite_used: registration.database.prepare("SELECT COALESCE(SUM(used_count), 0) AS count FROM invite_codes").get().count,
    sessions: registration.database.prepare("SELECT COUNT(*) AS count FROM sessions").get().count,
    users: registration.database.prepare("SELECT COUNT(*) AS count FROM users").get().count,
  };
}

function writeEvidence(file: string, value: unknown) {
  const directory = process.env.DADA_EVIDENCE_DIR_NOTICE;
  if (!directory) return;
  mkdirSync(directory, { recursive: true });
  writeFileSync(resolve(directory, file), `${JSON.stringify(value, null, 2)}\n`);
}

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

describe("TDD-WP1-NOTICE-001-registration-consent", () => {
  it("rejects missing/stale consent without side effects and records current consent atomically", async () => {
    const { registration, resend } = createHarness();
    const invite = registration.createInvite({ expiresAt: Date.parse("2026-07-29T09:30:00.000Z"), maxUses: 1 });
    const sent = await registration.sendRegistrationCode({ email: "notice-api@example.invalid", inviteCode: invite.code });
    const code = resend.readLatestCode("notice-api@example.invalid");
    const app = await createApp({ browserGate: false, networkBoundary: { allowTestPort: true }, registration });
    const before = snapshot(registration);
    const basePayload = {
      creator_name: "Notice User",
      privacy_notice_version: registrationNotice.version,
      registration_id: sent.registrationId,
      social_id: "@notice_user",
      verification_code: code,
    };

    const missingConsent = await app.inject({
      headers: { ...writeHeaders, "idempotency-key": "wp1-03-consent-missing-0000000000001" },
      method: "POST",
      payload: { ...basePayload, privacy_consent_accepted: false },
      url: "/api/v1/auth/register/complete",
    });
    expect(missingConsent.statusCode).toBe(400);
    expect(missingConsent.json()).toMatchObject({
      error: { details: { field_errors: [{ message_key: "auth.privacy.consent_required" }] } },
    });
    expect(snapshot(registration)).toEqual(before);

    const staleVersion = await app.inject({
      headers: { ...writeHeaders, "idempotency-key": "wp1-03-consent-stale-00000000000001" },
      method: "POST",
      payload: { ...basePayload, privacy_consent_accepted: true, privacy_notice_version: "stale-notice" },
      url: "/api/v1/auth/register/complete",
    });
    expect(staleVersion.statusCode).toBe(400);
    expect(staleVersion.json()).toMatchObject({
      error: { details: { field_errors: [{ message_key: "auth.privacy.notice_version_invalid" }] } },
    });
    expect(snapshot(registration)).toEqual(before);

    const completed = await app.inject({
      headers: { ...writeHeaders, "idempotency-key": "wp1-03-consent-success-0000000000001" },
      method: "POST",
      payload: { ...basePayload, privacy_consent_accepted: true },
      url: "/api/v1/auth/register/complete",
    });
    expect(completed.statusCode).toBe(200);
    const after = snapshot(registration);
    expect(after).toEqual({ consents: 1, credits: 1, invite_used: 1, sessions: 1, users: 1 });
    const consent = registration.database.prepare("SELECT notice_version, consented_at FROM privacy_consents").get();
    expect(consent).toEqual({
      consented_at: Date.parse("2026-07-28T09:30:00.000Z"),
      notice_version: registrationNotice.version,
    });

    writeEvidence("response.json", {
      accepted: completed.json().status,
      missing_consent: missingConsent.json().error.details.field_errors[0].message_key,
      stale_version: staleVersion.json().error.details.field_errors[0].message_key,
    });
    writeEvidence("db-diff.json", {
      after,
      before,
      consent_recorded_at: "2026-07-28T09:30:00.000Z",
      notice_content_sha256: registrationNotice.contentSha256,
      notice_effective_at: registrationNotice.effectiveAt,
      notice_version: registrationNotice.version,
    });
    await app.close();
  });
});
