#!/usr/bin/env node

const baseUrl = process.argv[2] ?? process.env.API_BASE_URL ?? "http://127.0.0.1:8080";
const email = `schema-migration-${Date.now()}@example.test`;

async function request(method, path, body, token) {
  const response = await fetch(`${baseUrl}${path}`, {
    method,
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    body: body === undefined ? undefined : JSON.stringify(body),
  });
  const text = await response.text();
  const data = text ? JSON.parse(text) : {};

  if (!response.ok) {
    throw new Error(`${method} ${path} failed: ${response.status} ${JSON.stringify(data)}`);
  }

  return data;
}

function assert(condition, message) {
  if (!condition) throw new Error(message);
}

async function main() {
  console.log(`testing schema migration idempotency via ${baseUrl}`);

  const registration = await request("POST", "/api/v1/registration/organization", {
    organization_name: "Migrationstest GmbH",
    email,
    accept_terms: true,
  });

  const approval = await request(
    "POST",
    `/api/v1/admin/organization-registrations/${registration.id}/approve`,
  );
  assert(approval.schema_name, "schema name missing after approval");

  const retry = await request(
    "POST",
    `/api/v1/admin/organization-registrations/${registration.id}/retry-provisioning`,
  );
  assert(retry.provisioned === true, "retry provisioning did not report success");
  assert(retry.schema_name === approval.schema_name, "retry provisioning schema mismatch");

  const login = await request("POST", "/api/v1/auth/login", {
    email,
    password: approval.dev_initial_password,
  });
  const token = login.access_token;
  await request("POST", "/api/v1/auth/select-organization", {
    organization_id: login.organization_id,
  }, token);

  const ranges = await request("GET", "/api/v1/number-ranges", undefined, token);
  for (const code of ["customers", "suppliers", "items", "activities", "outgoing_invoices", "incoming_invoices", "quotes"]) {
    assert(ranges.some((range) => range.code === code), `number range missing after retry: ${code}`);
  }

  const users = await request("GET", "/api/v1/organizations/current/users", undefined, token);
  const owner = users.find((user) => user.email === email);
  assert(owner?.roles.includes("owner"), "owner role missing after retry");
  assert(owner?.roles.includes("admin"), "admin role missing after retry");

  const communication = await request("POST", "/api/v1/communications", {
    communication_type: "internal_note",
    direction: "internal",
    subject: "Migrationstest",
    body: "Kommunikationstabellen sind vorhanden.",
    status: "open",
    occurred_at: null,
    links: [],
  }, token);
  assert(communication.id, "communication insert failed after retry");

  const navigationSettings = await request("PUT", "/api/v1/users/me/settings/navigation", {
    mode: "groups",
  }, token);
  assert(navigationSettings.mode === "groups", "navigation user setting was not saved");

  console.log("schema migration idempotency test ok");
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
