import assert from 'node:assert/strict';
import { randomUUID } from 'node:crypto';
import { config } from './config';
import { pool } from './db';
import {
  call,
  insertSyntheticCallSession,
  register,
  registerVerifiedGuardian,
  type Session,
} from './smokeSupport';
import type { SmokeContext } from './smokeProfileScenario';
import { ensurePaymentObligations } from './paymentService';
export const runJourneySmoke = async ({
  first,
  second,
  unrelated,
  representative,
  admin,
  accepted,
}: SmokeContext): Promise<void> => {
  const roomPath = `/v1/journeys/${accepted.journey.id}`;
  await call(`${roomPath}/reports`, 404, unrelated.token, 'POST', {
    category: 'conduct', description: 'A synthetic safety report that must not be accepted from an outsider.',
  });
  await call(`${roomPath}/reports`, 400, first.token, 'POST', {
    category: 'conduct', description: 'Too short',
  });
  const safetyReport = await call<{ report: { id: string; status: string } }>(
    `${roomPath}/reports`, 201, first.token, 'POST', {
      category: 'privacy', description: 'A synthetic privacy report for the API smoke test only.',
    },
  );
  assert.equal(safetyReport.report.status, 'open');
  const myReports = await call<{ reports: Array<{ id: string }> }>('/v1/me/reports', 200, first.token);
  assert(myReports.reports.some((item) => item.id === safetyReport.report.id));
  const otherReports = await call<{ reports: Array<{ id: string }> }>('/v1/me/reports', 200, second.token);
  assert(!otherReports.reports.some((item) => item.id === safetyReport.report.id));
  await call('/v1/admin/reports', 403, first.token);
  const viewer = await register('viewer');
  const readOnlyInvitation = await call<{ invitation: { id: string }; code: string }>(
    `${roomPath}/invitations`, 201, first.token, 'POST',
    { roleLabel: 'Family reader', permission: 'viewer' },
  );
  const writingInvitation = await call<{ invitation: { id: string }; code: string }>(
    `${roomPath}/invitations`, 201, second.token, 'POST',
    { roleLabel: 'Family contributor', permission: 'contributor' },
  );
  await call('/v1/invitations/accept', 404, first.token, 'POST', { code: readOnlyInvitation.code });
  await call('/v1/invitations/accept', 200, viewer.token, 'POST', { code: readOnlyInvitation.code });
  await call('/v1/invitations/accept', 200, unrelated.token, 'POST', { code: writingInvitation.code });
  const viewerJourneys = await call<{ journeys: Array<{ id: string; myPermission: string }> }>(
    '/v1/journeys', 200, viewer.token,
  );
  assert(viewerJourneys.journeys.some((journey) =>
    journey.id === accepted.journey.id && journey.myPermission === 'viewer'));
  await call(`${roomPath}/room`, 200, viewer.token);
  await call(`${roomPath}/messages`, 404, viewer.token, 'POST', {
    body: 'Forbidden', clientNonce: randomUUID(),
  });
  const nonce = randomUUID();
  const posted = await call<{ message: { id: string; authorUserId: string } }>(
    `${roomPath}/messages`, 201, unrelated.token, 'POST',
    { body: 'A family conversation', clientNonce: nonce },
  );
  assert.equal(posted.message.authorUserId, unrelated.user.id);
  const retried = await call<{ message: { id: string } }>(
    `${roomPath}/messages`, 201, unrelated.token, 'POST',
    { body: 'Ignored duplicate payload', clientNonce: nonce },
  );
  assert.equal(retried.message.id, posted.message.id);
  const room = await call<{ messages: Array<{ body: string }> }>(`${roomPath}/room`, 200, first.token);
  assert(room.messages.some((message) => message.body === 'A family conversation'));
  await call(`${roomPath}/invitations/${readOnlyInvitation.invitation.id}/revoke`,
    200, first.token, 'POST');
  await call(`${roomPath}/room`, 404, viewer.token);
  await call(`${roomPath}/decision`, 200, first.token);
  await call(`${roomPath}/decision`, 409, first.token, 'POST', { choice: 'continue' });
  const contactPath = `${roomPath}/contact`;
  await call(contactPath, 404, unrelated.token);
  await call(contactPath, 404, viewer.token);
  await call(`${contactPath}/email`, 400, first.token, 'PUT', { value: 'not-an-email' });
  await call(`${contactPath}/email`, 200, first.token, 'PUT', { value: 'first@example.test' });
  const beforeMutual = await call<{ fields: Array<{ field: string; myValue: string | null;
    counterpartReady: boolean; counterpartValue: string | null }> }>(contactPath, 200, second.token);
  assert.equal(beforeMutual.fields.find((field) => field.field === 'email')?.counterpartReady, true);
  assert.equal(beforeMutual.fields.find((field) => field.field === 'email')?.counterpartValue, null);
  assert(!JSON.stringify(beforeMutual).includes('first@example.test'));
  await call(`${contactPath}/phone`, 400, second.token, 'PUT', { value: '12345' });
  await call(`${contactPath}/email`, 200, second.token, 'PUT', { value: 'second@example.test' });
  const mutuallyVisible = await call<{ fields: Array<{ field: string; counterpartValue: string | null }> }>(
    contactPath, 200, second.token,
  );
  assert.equal(mutuallyVisible.fields.find((field) => field.field === 'email')?.counterpartValue,
    'first@example.test');
  await call(`${contactPath}/email`, 200, first.token, 'PUT', { value: 'first-updated@example.test' });
  const updated = await call<{ fields: Array<{ field: string; counterpartValue: string | null }> }>(
    contactPath, 200, second.token,
  );
  assert.equal(updated.fields.find((field) => field.field === 'email')?.counterpartValue,
    'first-updated@example.test');
  await call(`${contactPath}/email`, 200, first.token, 'DELETE');
  const revoked = await call<{ fields: Array<{ field: string; counterpartValue: string | null }> }>(
    contactPath, 200, second.token,
  );
  assert.equal(revoked.fields.find((field) => field.field === 'email')?.counterpartValue, null);
  await call(`${contactPath}/email`, 200, first.token, 'PUT', { value: 'first@example.test' });
  const groomGuardian = await registerVerifiedGuardian(first, 'Groom');
  const brideGuardian = await registerVerifiedGuardian(second, 'Bride');
  await call(`${roomPath}/call-guardian`, 404, first.token, 'PUT',
    { mode: 'guardian', guardianUserId: unrelated.user.id });
  await call(`${roomPath}/guardian-view`, 403, first.token);
  const futureTime = new Date(Date.now() + 2500).toISOString();
  const proposal = await call<{ meeting: { id: string } }>(
    `${roomPath}/meetings`, 201, first.token, 'POST',
    { startsAt: futureTime, timeZone: 'Europe/Berlin' },
  );
  const proposalNotifications = await call<{ notifications: Array<{ type: string; journeyId: string }> }>(
    '/v1/me/notifications', 200, second.token,
  );
  assert(proposalNotifications.notifications.some((item) =>
    item.type === 'meeting_proposed' && item.journeyId === accepted.journey.id));
  await call(`${roomPath}/meetings/${proposal.meeting.id}/confirm`, 404, first.token, 'POST');
  await call(`${roomPath}/meetings/${proposal.meeting.id}/confirm`, 200, second.token, 'POST');
  const guardianView = await call<{ people: Array<{ role: string; profile: unknown }> }>(
    `${roomPath}/guardian-view`, 200, groomGuardian.token,
  );
  assert.equal(guardianView.people.length, 4);
  assert(guardianView.people.some((person) => person.role === 'bride' && person.profile));
  await call(`${roomPath}/room`, 403, groomGuardian.token);
  const scheduledTimeline = await call<{ events: Array<{ type: string }> }>(
    `/v1/requests/${accepted.requestId}/workspace`, 200, first.token,
  );
  assert(scheduledTimeline.events.some((item) => item.type === 'meeting_proposed'));
  assert(scheduledTimeline.events.some((item) => item.type === 'meeting_confirmed'));
  const awaitingGuardians = await call<{ call: { confirmationCount: number;
    allPartiesConfirmed: boolean } }>(`${roomPath}/call`, 200, first.token);
  assert.equal(awaitingGuardians.call.confirmationCount, 2);
  assert.equal(awaitingGuardians.call.allPartiesConfirmed, false);
  await call(`${roomPath}/call/schedule-confirm`, 403, first.token, 'POST');
  await call(`${roomPath}/call/schedule-confirm`, 200, groomGuardian.token, 'POST');
  const oneGuardianConfirmed = await call<{ call: { confirmationCount: number;
    allPartiesConfirmed: boolean } }>(`${roomPath}/call`, 200, first.token);
  assert.equal(oneGuardianConfirmed.call.confirmationCount, 3);
  assert.equal(oneGuardianConfirmed.call.allPartiesConfirmed, false);
  const allConfirmed = await call<{ call: { confirmationCount: number;
    allPartiesConfirmed: boolean } }>(
      `${roomPath}/call/schedule-confirm`, 200, brideGuardian.token, 'POST',
    );
  assert.equal(allConfirmed.call.confirmationCount, 4);
  assert.equal(allConfirmed.call.allPartiesConfirmed, true);
  const senderCheckout = await call<{ paymentRequiredFromActor: boolean; payments: unknown[] }>(
    `${roomPath}/checkout`, 200, first.token,
  );
  const recipientCheckout = await call<{ paymentRequiredFromActor: boolean; payments: unknown[] }>(
    `${roomPath}/checkout`, 200, second.token,
  );
  assert.equal(senderCheckout.paymentRequiredFromActor, true);
  assert.equal(senderCheckout.payments.length, 1);
  assert.equal(recipientCheckout.paymentRequiredFromActor, true);
  assert.equal(recipientCheckout.payments.length, 1);
  const scheduleNotifications = await call<{ notifications: Array<{ type: string; title: string }> }>(
    '/v1/me/notifications', 200, first.token,
  );
  assert(scheduleNotifications.notifications.some((item) =>
    item.type === 'schedule_confirmed' && item.title === 'اكتملت موافقات الموعد'));
  const callReady = await call<{ call: { guardiansReady: boolean; guardiansPresent: boolean;
    canJoin: boolean; allPartiesConfirmed: boolean;
    mediaProvider: { name: string; configured: boolean }; slots: Array<{
    role: string; userId: string;
  }> } }>(`${roomPath}/call`, 200, first.token);
  assert.equal(callReady.call.guardiansReady, true);
  assert.equal(callReady.call.guardiansPresent, false);
  assert.equal(callReady.call.canJoin, false);
  assert.equal(callReady.call.allPartiesConfirmed, true);
  assert.equal(callReady.call.mediaProvider.name, 'livekit');
  assert.equal(callReady.call.mediaProvider.configured, config.liveKit.configured);
  assert.equal(callReady.call.slots.length, 4);
  assert.deepEqual(callReady.call.slots.map((slot) => slot.role),
    ['groom', 'groomGuardian', 'bride', 'brideGuardian']);
  await call(`${roomPath}/call/join`, 404, viewer.token, 'POST');
  await call(`${roomPath}/call/join`, 409, first.token, 'POST');
  await ensurePaymentObligations(proposal.meeting.id);
  await pool.query(
    `UPDATE meeting_payment_obligations SET status='paid',method='sham_cash',amount=10,currency='USD',
       paid_by_user_id=beneficiary_user_id,reviewed_at=NOW() WHERE meeting_id=$1`,
    [proposal.meeting.id],
  );
  const paidCheckout = await call<{ allPaid: boolean; paymentRequiredFromActor: boolean; payments: unknown[] }>(
    `${roomPath}/checkout`, 200, second.token);
  assert.deepEqual([paidCheckout.allPaid, paidCheckout.paymentRequiredFromActor, paidCheckout.payments.length], [true, false, 0]);
  await call(`${roomPath}/meetings/${proposal.meeting.id}/attendance`, 409, first.token, 'POST');
  const callSessions: Array<{ session: Session; sessionId: string }> = [];
  for (const session of [groomGuardian, brideGuardian, first, second]) {
    if (config.liveKit.configured) {
      const joined = await call<{ sessionId: string; media: {
        provider: string; serverUrl: string; roomName: string; participantToken: string;
        encryptionKey: string; observer: boolean;
      } }>(`${roomPath}/call/join`, 201, session.token, 'POST');
      assert.equal(joined.media.provider, 'livekit');
      assert.equal(joined.media.serverUrl, config.liveKit.url);
      assert.equal(joined.media.roomName, `family-${proposal.meeting.id}`);
      assert.equal(joined.media.participantToken.split('.').length, 3);
      assert.equal(joined.media.encryptionKey.length > 30, true);
      assert.equal(joined.media.observer, false);
      callSessions.push({ session, sessionId: joined.sessionId });
    } else {
      if (callSessions.length === 0) {
        await call(`${roomPath}/call/join`, 503, session.token, 'POST');
      }
      callSessions.push({
        session,
        sessionId: await insertSyntheticCallSession(proposal.meeting.id, session.user.id),
      });
    }
    if (session === groomGuardian) {
      const waiting = await call<{ call: { canJoin: boolean; guardiansPresent: boolean } }>(
        `${roomPath}/call`, 200, first.token,
      );
      assert.equal(waiting.call.guardiansPresent, false);
      assert.equal(waiting.call.canJoin, false);
    }
    if (session === brideGuardian) {
      const admitted = await call<{ call: { canJoin: boolean; guardiansPresent: boolean } }>(
        `${roomPath}/call`, 200, first.token,
      );
      assert.equal(admitted.call.guardiansPresent, true);
      assert.equal(admitted.call.canJoin, true);
    }
  }
  await call(`${roomPath}/call/leave`, 200, brideGuardian.token, 'POST',
    { sessionId: callSessions[1].sessionId });
  const guardianGone = await call<{ call: { canJoin: boolean; guardiansPresent: boolean } }>(
    `${roomPath}/call`, 200, first.token,
  );
  assert.equal(guardianGone.call.guardiansPresent, false);
  assert.equal(guardianGone.call.canJoin, false);
  const callTimeline = await call<{ events: Array<{ type: string }> }>(
    `/v1/requests/${accepted.requestId}/workspace`, 200, first.token,
  );
  assert(callTimeline.events.some((item) => item.type === 'call_joined'));
  assert(callTimeline.events.some((item) => item.type === 'call_left'));
  const remainingCandidate = await call<{ call: { canJoin: boolean } }>(
    `${roomPath}/call/state?sessionId=${callSessions[2].sessionId}`, 200, first.token);
  assert.equal(remainingCandidate.call.canJoin, true);
  if (config.liveKit.configured) {
    const rejoinedGuardian = await call<{ sessionId: string }>(
      `${roomPath}/call/join`, 201, brideGuardian.token, 'POST');
    callSessions[1].sessionId = rejoinedGuardian.sessionId;
    await call(`${roomPath}/call/join`, 409, first.token, 'POST');
  } else {
    callSessions[1].sessionId = await insertSyntheticCallSession(
      proposal.meeting.id,
      brideGuardian.user.id,
    );
  }
  const guardianHeartbeat = await call<{ call: { guardiansPresent: boolean } }>(
    `${roomPath}/call/state?sessionId=${callSessions[0].sessionId}`, 200, groomGuardian.token,
  );
  assert.equal(guardianHeartbeat.call.guardiansPresent, true);
  await call(`${roomPath}/meetings/${proposal.meeting.id}/attendance`, 409, first.token, 'POST');
  for (const [firstIndex, secondIndex] of [[0, 1], [1, 2], [2, 3]]) {
    const a = callSessions[firstIndex];
    const b = callSessions[secondIndex];
    const oneSided = await call<{ confirmed: boolean }>(
      `${roomPath}/call/connected`, 200, a.session.token, 'POST',
      { sessionId: a.sessionId, peerSessionId: b.sessionId },
    );
    assert.equal(oneSided.confirmed, false);
    const bothSides = await call<{ confirmed: boolean }>(
      `${roomPath}/call/connected`, 200, b.session.token, 'POST',
      { sessionId: b.sessionId, peerSessionId: a.sessionId },
    );
    assert.equal(bothSides.confirmed, true);
  }
  const remaining = Date.parse(futureTime) - Date.now();
  if (remaining > 0) await new Promise((resolve) => setTimeout(resolve, remaining + 100));
  await call(`${roomPath}/meetings/${proposal.meeting.id}/attendance`, 200, first.token, 'POST');
  const finalAttendance = await call<{ decisionReady: boolean }>(
    `${roomPath}/meetings/${proposal.meeting.id}/attendance`, 200, second.token, 'POST',
  );
  assert.equal(finalAttendance.decisionReady, true);
  await call(`${roomPath}/call/join`, 409, groomGuardian.token, 'POST');
  const secret = 'First participant private smoke-test notes';
  await call(`${roomPath}/decision`, 200, first.token, 'POST',
    { choice: 'continue', privateNotes: secret });
  const otherDecision = await call<{ decision: { myChoice: string | null; myPrivateNotes: string | null } }>(
    `${roomPath}/decision`, 200, second.token,
  );
  assert.equal(otherDecision.decision.myChoice, null);
  assert(!JSON.stringify(otherDecision).includes(secret));
  await call(`${roomPath}/decision`, 404, unrelated.token);
  await call(`${roomPath}/decision`, 200, second.token, 'POST',
    { choice: 'apologize', privateNotes: 'Second participant private notes' });
  const resolved = await call<{ decision: { outcome: string; myPrivateNotes: string } }>(
    `${roomPath}/decision`, 200, first.token,
  );
  assert.equal(resolved.decision.outcome, 'closed');
  assert.equal(resolved.decision.myPrivateNotes, secret);
  await call(`${roomPath}/room`, 404, unrelated.token);
  await call(`${roomPath}/messages`, 409, first.token, 'POST',
    { body: 'Closed', clientNonce: randomUUID() });
  const closedContact = await call<{ closed: boolean; fields: Array<{ counterpartValue: string | null }> }>(
    contactPath, 200, first.token,
  );
  assert.equal(closedContact.closed, true);
  assert(closedContact.fields.every((field) => field.counterpartValue === null));
  await call(`${contactPath}/email`, 409, first.token, 'PUT', { value: 'first@example.test' });
  const adminReports = await call<{ reports: Array<{ id: string; description: string }> }>(
    '/v1/admin/reports', 200, admin.token,
  );
  assert(adminReports.reports.some((item) => item.id === safetyReport.report.id && item.description.includes('synthetic')));
  await call(`/v1/admin/reports/${safetyReport.report.id}`, 400, admin.token, 'PATCH', {
    status: 'resolved', adminNote: 'No',
  });
  await call(`/v1/admin/reports/${safetyReport.report.id}`, 200, admin.token, 'PATCH', {
    status: 'resolved', adminNote: 'Reviewed synthetic smoke-test report.',
  });
  const correction = await call<{ correction: { id: string } }>(
    '/v1/me/profile-corrections', 201, first.token, 'POST', {
      field: 'birthPlace', proposedValue: 'Hamburg',
      reason: 'The recorded birthplace was entered incorrectly during profile creation.',
    },
  );
  await call('/v1/me/profile-corrections', 409, first.token, 'POST', {
    field: 'displayName', proposedValue: 'Changed name',
    reason: 'A second correction must wait for the first administrator review.',
  });
  const correctionQueue = await call<{ corrections: Array<{ id: string }> }>(
    '/v1/admin/profile-corrections', 200, admin.token,
  );
  assert(correctionQueue.corrections.some((item) => item.id === correction.correction.id));
  await call(`/v1/admin/profile-corrections/${correction.correction.id}/review`, 200,
    admin.token, 'PATCH', { decision: 'approved', note: 'Verified correction request.' });
  const correctedProfile = await call<{ profile: { birthPlace: string; isPublished: boolean;
    approvalStatus: string } }>('/v1/me/profile', 200, first.token);
  assert.equal(correctedProfile.profile.birthPlace, 'Hamburg');
  assert.equal(correctedProfile.profile.isPublished, true);
  assert.equal(correctedProfile.profile.approvalStatus, 'approved');
  const rejectedCorrection = await call<{ correction: { id: string } }>(
    '/v1/me/profile-corrections', 201, first.token, 'POST', {
      field: 'displayName', proposedValue: 'Smoke Corrected',
      reason: 'This is a synthetic request to test rejection with an administrator note.',
    },
  );
  await call(`/v1/admin/profile-corrections/${rejectedCorrection.correction.id}/review`, 200,
    admin.token, 'PATCH', { decision: 'rejected', note: 'The request does not meet the correction policy.' });
  await pool.query(
    "UPDATE profiles SET gender='woman',marital_status='single' WHERE user_id=$1",
    [unrelated.user.id],
  );
  const exceptionRequestId = randomUUID();
  const exceptionJourneyId = randomUUID();
  const exceptionMeetingId = randomUUID();
  await pool.query(
    `INSERT INTO engagement_requests (id,sender_user_id,recipient_user_id,status)
     VALUES ($1,$2,$3,'accepted')`,
    [exceptionRequestId, first.user.id, unrelated.user.id],
  );
  await pool.query(
    `INSERT INTO journeys (id,request_id,first_user_id,second_user_id)
     VALUES ($1,$2,$3,$4)`,
    [exceptionJourneyId, exceptionRequestId, first.user.id, unrelated.user.id],
  );
  await pool.query(
    `INSERT INTO meeting_proposals
       (id,journey_id,proposed_by,starts_at,time_zone,status,video_required)
     VALUES ($1,$2,$3,NOW()+INTERVAL '1 hour','Europe/Berlin','confirmed',TRUE)`,
    [exceptionMeetingId, exceptionJourneyId, first.user.id],
  );
  const exceptionCallPath = `/v1/journeys/${exceptionJourneyId}`;
  await call(`${exceptionCallPath}/call-guardian`, 200, first.token, 'PUT',
    { mode: 'guardian', guardianUserId: groomGuardian.user.id });
  await call(`${exceptionCallPath}/call-guardian`, 200, unrelated.token, 'PUT',
    { mode: 'exception' });
  await call(`${exceptionCallPath}/call/schedule-confirm`, 200, groomGuardian.token, 'POST');
  await call(`${exceptionCallPath}/call/schedule-confirm`, 200, representative.token, 'POST');
  const exceptionWaiting = await call<{ call: { guardiansReady: boolean;
    guardiansPresent: boolean; canJoin: boolean; slots: Array<{
      userId: string | null; isRepresentative: boolean;
    }> } }>(
      `${exceptionCallPath}/call`, 200, unrelated.token,
    );
  assert.equal(exceptionWaiting.call.guardiansReady, true);
  assert.equal(exceptionWaiting.call.guardiansPresent, false);
  assert.equal(exceptionWaiting.call.canJoin, false);
  assert.equal(exceptionWaiting.call.slots.filter((slot) => slot.isRepresentative).length, 1);
  assert.equal(new Set(exceptionWaiting.call.slots.map((slot) => slot.userId)).size, 4);
  await call(`${exceptionCallPath}/guardian-view`, 200, representative.token);
  await call(`${exceptionCallPath}/room`, 403, representative.token);
  await call(`${exceptionCallPath}/call/join`, 409, unrelated.token, 'POST');
  await ensurePaymentObligations(exceptionMeetingId);
  await pool.query(
    `UPDATE meeting_payment_obligations SET status='paid',method='sham_cash',amount=10,currency='USD',
       paid_by_user_id=beneficiary_user_id,reviewed_at=NOW() WHERE meeting_id=$1`,
    [exceptionMeetingId],
  );
  const representativeCallSession = config.liveKit.configured
    ? await call<{ sessionId: string }>(
      `${exceptionCallPath}/call/join`, 201, representative.token, 'POST')
    : { sessionId: await insertSyntheticCallSession(exceptionMeetingId, representative.user.id) };
  if (config.liveKit.configured) {
    await call(`${exceptionCallPath}/call/join`, 409, unrelated.token, 'POST');
  }
  const guardianCallSession = config.liveKit.configured
    ? await call<{ sessionId: string }>(
      `${exceptionCallPath}/call/join`, 201, groomGuardian.token, 'POST')
    : { sessionId: await insertSyntheticCallSession(exceptionMeetingId, groomGuardian.user.id) };
  const exceptionAdmitted = await call<{ call: { canJoin: boolean; guardiansPresent: boolean } }>(
    `${exceptionCallPath}/call`, 200, unrelated.token,
  );
  assert.equal(exceptionAdmitted.call.guardiansPresent, true);
  assert.equal(exceptionAdmitted.call.canJoin, true);
  if (config.liveKit.configured) {
    await call(`${exceptionCallPath}/call/join`, 201, unrelated.token, 'POST');
    await call(`${exceptionCallPath}/call/join`, 201, first.token, 'POST');
  } else {
    await insertSyntheticCallSession(exceptionMeetingId, unrelated.user.id);
    await insertSyntheticCallSession(exceptionMeetingId, first.user.id);
  }
  await call(`${exceptionCallPath}/call/leave`, 200, representative.token, 'POST',
    { sessionId: representativeCallSession.sessionId });
  const exceptionGuardianGone = await call<{ call: { canJoin: boolean } }>(
    `${exceptionCallPath}/call`, 200, unrelated.token,
  );
  assert.equal(exceptionGuardianGone.call.canJoin, false);
  await call(`${exceptionCallPath}/call/leave`, 200, groomGuardian.token, 'POST',
    { sessionId: guardianCallSession.sessionId });
  await call(`/admin/users/${unrelated.user.id}/status`, 200, admin.token, 'PATCH', { isActive: false });
  await call('/auth/me', 401, unrelated.token);
  await call(`/admin/users/${unrelated.user.id}/status`, 200, admin.token, 'PATCH', { isActive: true });
  const managedUsername = `managed-${unrelated.user.id.slice(0, 8)}`;
  const managedEmail = `managed-${unrelated.user.id}@example.test`;
  await call(`/admin/users/${unrelated.user.id}`, 200, admin.token, 'PATCH', {
    displayName: 'Managed smoke account', email: managedEmail, username: managedUsername,
  });
  const managedProfile = await call<{ profile: Record<string, unknown> & { version: number } }>(
    `/admin/users/${unrelated.user.id}/profile`, 200, admin.token,
  );
  const updatedProfile = await call<{ profile: { city: string; approvalStatus: string; version: number } }>(
    `/admin/users/${unrelated.user.id}/profile`, 200, admin.token, 'PATCH', {
      ...managedProfile.profile, displayName: 'Managed smoke account', country: 'Managed city, Germany',
      publicationRequested: true, expectedVersion: managedProfile.profile.version,
    },
  );
  assert.equal(updatedProfile.profile.city, 'Managed city, Germany');
  assert.equal(updatedProfile.profile.approvalStatus, 'approved');
  await call(`/admin/users/${unrelated.user.id}/profile`, 409, admin.token, 'PATCH', {
    ...managedProfile.profile, displayName: 'Managed smoke account', country: 'Stale city, Germany',
    publicationRequested: true, expectedVersion: managedProfile.profile.version,
  });
  const firstAccount = await pool.query<{ email: string }>('SELECT email FROM users WHERE id=$1', [first.user.id]);
  await call(`/admin/users/${unrelated.user.id}`, 409, admin.token, 'PATCH', {
    displayName: 'Managed smoke account', email: firstAccount.rows[0].email, username: managedUsername,
  });
  const replacementPassword = `Changed-${randomUUID()}-Password!`;
  await call(`/admin/users/${unrelated.user.id}/password`, 200, admin.token, 'PATCH', {
    password: replacementPassword,
  });
  const managedSession = await call<Session>('/auth/login', 200, undefined, 'POST', {
    identifier: managedUsername, password: replacementPassword,
  });
  await call(`/admin/users/${unrelated.user.id}`, 400, admin.token, 'DELETE', {
    confirmed: false,
  });
  await call(`/admin/users/${unrelated.user.id}`, 200, admin.token, 'DELETE', {
    confirmed: true,
  });
  await call('/auth/me', 401, managedSession.token);
  const overview = await call<{ users: Array<{ id: string; linkedMembers: unknown[] }> }>(
    '/admin/overview', 200, admin.token,
  );
  assert(!overview.users.some((item) => item.id === unrelated.user.id));
  assert(overview.users.every((item) => Array.isArray(item.linkedMembers)));
  await call('/v1/me/guardian-change', 400, first.token, 'POST', { reason: 'short' });
  const guardianChangeReason = 'The family needs to replace the current guardian for this test.';
  await call('/v1/me/guardian-change', 200, first.token, 'POST', { reason: guardianChangeReason });
  await call('/auth/me', 401, groomGuardian.token);
  const guardianAfterChange = await call<{ guardian: { satisfied: boolean; invitations: Array<{
    status: string; guardianUserId: string | null;
  }> } }>('/v1/me/guardian-verification', 200, first.token);
  assert.equal(guardianAfterChange.guardian.satisfied, false);
  assert(!guardianAfterChange.guardian.invitations.some((item) => item.status === 'verified'));
  await call('/v1/me/guardian-qr', 201, first.token, 'POST');
  const guardianChanges = await call<{ changes: Array<{
    candidateUserId: string; formerGuardianUserId: string; reason: string;
  }> }>('/v1/admin/guardian-changes', 200, admin.token);
  assert(guardianChanges.changes.some((item) => item.candidateUserId === first.user.id
    && item.formerGuardianUserId === groomGuardian.user.id && item.reason === guardianChangeReason));
  await call(`/admin/users/${first.user.id}`, 200, admin.token, 'DELETE', { confirmed: true });
  await call('/auth/me', 401, first.token);
  await call('/auth/me', 401, groomGuardian.token);
  const cascadeOverview = await call<{ users: Array<{ id: string }> }>(
    '/admin/overview', 200, admin.token,
  );
  assert(!cascadeOverview.users.some((item) => item.id === first.user.id));
  assert(!cascadeOverview.users.some((item) => item.id === groomGuardian.user.id));
};
