import assert from 'node:assert/strict';
import { promises as fs } from 'node:fs';
import path from 'node:path';

process.env.APP_ENV = 'test';
process.env.ALLOW_LOCAL_FALLBACK = 'true';

const originalConsoleWarn = console.warn;
console.warn = (..._args: unknown[]) => undefined;

const dataDirectory = path.resolve(__dirname, '../data');
const trackedDataFiles = [
  'agent-dental-knowledge-audit.json',
  'agent-dental-knowledge-versions.json',
  'agent-dental-knowledge.json',
  'appointments.json',
  'budgets.json',
  'communication-logs.json',
  'communication-settings.json',
  'document-sequences.json',
  'doctor-schedule-overrides.json',
  'doctor-schedules.json',
  'inventory.json',
  'notification-feed.json',
  'odontogram.json',
  'patient-attachments.json',
  'password-recovery-requests.json',
  'patients.json',
  'patient-portal-access.json',
  'recipes.json',
  'settings.json',
  'treatments.json',
  'transactions.json',
  'users.json',
] as const;

const appointmentSlots = {
  backendCreate: '2030-04-08T09:00:00-05:00',
  backendConflict: '2030-04-08T09:30:00-05:00',
  patientPortal: '2030-04-09T10:00:00-05:00',
  doctorPortal: '2030-04-10T11:00:00-05:00',
  rescheduleOriginal: '2030-04-11T09:00:00-05:00',
  rescheduleUpdated: '2030-04-11T10:30:00-05:00',
  updateConflictFirst: '2030-04-12T09:00:00-05:00',
  updateConflictSecond: '2030-04-12T10:00:00-05:00',
  scheduleWeekly: '2030-04-17',
  scheduleOverride: '2030-04-18',
} as const;

type JsonRecord = Record<string, unknown>;

type HttpTestClient = {
  request: (path: string, init?: RequestInit) => Promise<Response>;
  close: () => Promise<void>;
};

type AdminUser = {
  id: string;
  email: string;
  role: string;
};

type PatientSummary = {
  id: string;
  nombres: string;
  apellidos: string;
  email: string | null;
};

type PatientSession = {
  token: string;
  access: {
    id: string;
    patientId: string;
    email: string;
  };
  patient: PatientSummary;
};

type DataSnapshotEntry = {
  fileName: string;
  content: string | null;
};

let cachedApp: typeof import('../src/index').app | null = null;
let cachedCreateHttpTestClient: typeof import('./helpers/http-test-client').createHttpTestClient | null = null;

const loadApp = async () => {
  if (!cachedApp) {
    const module = await import('../src/index');
    cachedApp = module.app;
  }

  return cachedApp;
};

const loadHttpClientFactory = async () => {
  if (!cachedCreateHttpTestClient) {
    const module = await import('./helpers/http-test-client');
    cachedCreateHttpTestClient = module.createHttpTestClient;
  }

  return cachedCreateHttpTestClient;
};

const captureDataSnapshots = async (): Promise<DataSnapshotEntry[]> =>
  Promise.all(
    trackedDataFiles.map(async (fileName) => {
      try {
        const content = await fs.readFile(path.join(dataDirectory, fileName), 'utf8');
        return {
          fileName,
          content,
        };
      } catch (error) {
        if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
          return {
            fileName,
            content: null,
          };
        }

        throw error;
      }
    }),
  );

const restoreDataSnapshots = async (snapshots: DataSnapshotEntry[]) => {
  await fs.mkdir(dataDirectory, { recursive: true });

  for (const snapshot of snapshots) {
    const filePath = path.join(dataDirectory, snapshot.fileName);

    if (snapshot.content === null) {
      await fs.rm(filePath, { force: true });
      continue;
    }

    await fs.writeFile(filePath, snapshot.content);
  }
};

const withHttpClient = async (run: (client: HttpTestClient) => Promise<void>) => {
  const app = await loadApp();
  const createHttpTestClient = await loadHttpClientFactory();
  const client = await createHttpTestClient(app);

  try {
    await run(client);
  } finally {
    await client.close();
  }
};

const buildJsonRequest = (body: JsonRecord, headers?: HeadersInit): RequestInit => ({
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    ...(headers ?? {}),
  },
  body: JSON.stringify(body),
});

const buildAdminSessionHeaders = (admin: AdminUser) => ({
  'x-user-id': admin.id,
  'x-user-role': admin.role,
});

const assertDataSourceHeader = (response: Response) => {
  assert.ok(['database', 'local-fallback'].includes(response.headers.get('x-data-source') ?? ''));
};

const loginAsAdmin = async (client: HttpTestClient): Promise<AdminUser> => {
  const response = await client.request(
    '/api/auth/login',
    buildJsonRequest({
      email: 'admin@dentaflow.local',
      password: 'admin123',
    }),
  );

  const payload = (await response.json()) as {
    user?: AdminUser;
  };

  assert.equal(response.status, 200);
  assert.ok(payload.user?.id);
  assert.equal(payload.user?.email, 'admin@dentaflow.local');
  assert.equal(payload.user?.role, 'ADMIN');

  return payload.user;
};

const loginWithCredentials = async (
  client: HttpTestClient,
  email: string,
  password: string,
): Promise<{
  response: Response;
  payload: {
    user?: {
      id: string;
      email: string;
      role: string;
    };
    error?: string;
  };
}> => {
  const response = await client.request(
    '/api/auth/login',
    buildJsonRequest({
      email,
      password,
    }),
  );

  const payload = (await response.json()) as {
    user?: {
      id: string;
      email: string;
      role: string;
    };
    error?: string;
  };

  return {
    response,
    payload,
  };
};

const listPatients = async (client: HttpTestClient): Promise<PatientSummary[]> => {
  const response = await client.request('/api/patients');
  const payload = (await response.json()) as unknown;

  assert.equal(response.status, 200);
  assert.ok(Array.isArray(payload));

  return payload as PatientSummary[];
};

const createPatientFixture = async (client: HttpTestClient, suffix: string): Promise<PatientSummary> => {
  const response = await client.request('/api/patients', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      dni: `7${suffix.slice(-7)}`,
      nombres: 'Paciente',
      apellidos: `Suite ${suffix}`,
      email: `suite.${suffix}@dentaflow.local`,
      telefono: '+51 900 000 000',
    }),
  });

  const payload = (await response.json()) as PatientSummary;

  assert.equal(response.status, 201);
  assert.ok(payload.id);

  return payload;
};

const ensurePatients = async (client: HttpTestClient, minimumCount: number): Promise<PatientSummary[]> => {
  let patients = await listPatients(client);

  while (patients.length < minimumCount) {
    const suffix = `${Date.now()}${patients.length}`;
    await createPatientFixture(client, suffix);
    patients = await listPatients(client);
  }

  return patients;
};

const ensurePatientPortalAccess = async (client: HttpTestClient, patientId: string, email: string, password: string) => {
  const response = await client.request(`/api/patients/${patientId}/portal-access`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      email,
      password,
      active: true,
    }),
  });

  const payload = (await response.json()) as {
    access?: {
      patientId: string;
      email: string;
      active: boolean;
    };
  };

  assert.equal(response.status, 200);
  assert.equal(payload.access?.patientId, patientId);
  assert.equal(payload.access?.email, email);
  assert.equal(payload.access?.active, true);
};

const loginAsPatient = async (client: HttpTestClient, email: string, password: string): Promise<PatientSession> => {
  const response = await client.request(
    '/api/patient-auth/login',
    buildJsonRequest({
      email,
      password,
    }),
  );

  const payload = (await response.json()) as Partial<PatientSession>;

  assert.equal(response.status, 200);
  assert.equal(typeof payload.token, 'string');
  assert.equal(payload.access?.email, email);
  assert.ok(payload.patient?.id);

  return payload as PatientSession;
};

const getPatientPortalNotifications = async (client: HttpTestClient, token: string) => {
  const response = await client.request('/api/patient-portal/notifications', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  const payload = (await response.json()) as {
    notifications?: Array<{
      id: string;
      title: string;
      message: string;
      readAt: string | null;
    }>;
    unreadCount?: number;
  };

  assert.equal(response.status, 200);
  return payload;
};

const getDoctorNotifications = async (client: HttpTestClient, doctorUserId: string) => {
  const response = await client.request('/api/doctor-mobile/notifications', {
    headers: {
      'x-operational-user-id': doctorUserId,
    },
  });

  const payload = (await response.json()) as {
    notifications?: Array<{
      id: string;
      title: string;
      message: string;
      readAt: string | null;
    }>;
    unreadCount?: number;
  };

  assert.equal(response.status, 200);
  return payload;
};

const getJson = async <T>(client: HttpTestClient, requestPath: string, init?: RequestInit) => {
  const response = await client.request(requestPath, init);
  const payload = (await response.json()) as T;
  return { response, payload };
};

type TestCase = {
  name: string;
  run: () => Promise<void>;
};

const tests: TestCase[] = [];

const register = (name: string, run: () => Promise<void>) => {
  tests.push({ name, run });
};

register('GET /health devuelve estado del servicio', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request('/health');
    const payload = (await response.json()) as {
      status: string;
      environment: string;
      fallbackPolicy: string;
      database: {
        ok: boolean;
        configured: boolean;
      };
    };

    assert.equal(response.status, 200);
    assert.equal(payload.status, 'ok');
    assert.ok(payload.environment.length > 0);
    assert.ok(['enabled', 'disabled'].includes(payload.fallbackPolicy));
    assert.equal(payload.database.configured, true);
    assert.equal(typeof payload.database.ok, 'boolean');
  });
});

register('GET /health/ready expone readiness del backend', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request('/health/ready');
    const payload = (await response.json()) as {
      status: string;
      fallbackPolicy: string;
      database: {
        ok: boolean;
      };
    };

    assert.ok([200, 503].includes(response.status));
    assert.ok(['ready', 'not-ready'].includes(payload.status));
    assert.ok(['enabled', 'disabled'].includes(payload.fallbackPolicy));
    assert.equal(typeof payload.database.ok, 'boolean');
  });
});

register('POST /api/auth/login autentica el admin demo', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    assert.ok(admin.id);
  });
});

register('POST /api/auth/login rechaza credenciales invalidas', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request(
      '/api/auth/login',
      buildJsonRequest({
        email: 'admin@dentaflow.local',
        password: 'incorrecta',
      }),
    );

    const payload = (await response.json()) as { error?: string };

    assert.equal(response.status, 401);
    assert.equal(payload.error, 'Credenciales invalidas');
  });
});

register('GET /api/agent-dental/knowledge exige sesion de staff', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request('/api/agent-dental/knowledge');
    const payload = (await response.json()) as { error?: string };

    assert.equal(response.status, 401);
    assert.equal(payload.error, 'Sesion de staff no valida.');
  });
});

register('POST /api/agent-dental/knowledge bloquea rol inconsistente y permite admin', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);

    const mismatchResponse = await client.request('/api/agent-dental/knowledge', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-user-id': admin.id,
        'x-user-role': 'DENTIST',
      },
      body: JSON.stringify({
        title: 'Protocolo prueba mismatch',
        summary: 'No deberia guardarse con rol incorrecto',
        answer: 'Respuesta de prueba',
        audience: ['staff'],
        keywords: ['prueba'],
        steps: ['Paso 1'],
        actions: [],
        relatedContextIds: ['configuration'],
      }),
    });

    const mismatchPayload = (await mismatchResponse.json()) as { error?: string };

    assert.equal(mismatchResponse.status, 403);
    assert.equal(mismatchPayload.error, 'La sesion no coincide con el rol informado.');

    const createResponse = await client.request('/api/agent-dental/knowledge', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...buildAdminSessionHeaders(admin),
      },
      body: JSON.stringify({
        title: 'Protocolo automatizado de prueba',
        summary: 'Articulo creado desde test de integracion',
        answer: 'Este contenido valida autorizacion del backend.',
        audience: ['staff'],
        keywords: ['protocolo', 'automatizado', 'prueba'],
        steps: ['Abrir configuracion', 'Validar respuesta'],
        actions: [],
        relatedContextIds: ['configuration'],
      }),
    });

    const createPayload = (await createResponse.json()) as {
      article?: {
        id: string;
        title: string;
      };
    };

    assert.equal(createResponse.status, 201);
    assert.ok(createPayload.article?.id);
    assert.equal(createPayload.article?.title, 'Protocolo automatizado de prueba');
  });
});

register('GET /api/appointments responde con coleccion de citas', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request('/api/appointments');
    const payload = (await response.json()) as unknown;

    assert.equal(response.status, 200);
    assert.ok(Array.isArray(payload));
  });
});

register('POST /api/appointments valida campos obligatorios', async () => {
  await withHttpClient(async (client) => {
    const response = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: '',
        fecha: '',
        motivo: '',
      }),
    });

    const payload = (await response.json()) as { error?: string };

    assert.equal(response.status, 400);
    assert.equal(payload.error, 'El motivo de la cita es obligatorio');
  });
});

register('POST /api/appointments crea una cita completa con odontologo asignado', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;

    const response = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patient.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.backendCreate,
        motivo: 'Reserva completa automatizada',
        notas: 'Creada desde la suite de integracion',
      }),
    });

    const payload = (await response.json()) as {
      id: string;
      fecha: string;
      motivo: string;
      estado: string;
      notas: string | null;
      pacienteId: string;
      paciente: {
        id: string;
      };
      dentista: {
        id: string;
        nombre: string;
      };
    };

    assert.equal(response.status, 201);
    assertDataSourceHeader(response);
    assert.ok(payload.id);
    assert.equal(payload.fecha, '2030-04-08T14:00:00.000Z');
    assert.equal(payload.motivo, 'Reserva completa automatizada');
    assert.equal(payload.estado, 'PROGRAMADA');
    assert.equal(payload.notas, 'Creada desde la suite de integracion');
    assert.equal(payload.pacienteId, patient.id);
    assert.equal(payload.paciente.id, patient.id);
    assert.equal(payload.dentista.id, admin.id);
  });
});

register('POST /api/appointments rechaza conflicto de horario del odontologo', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 2);

    const firstResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[0]!.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.backendConflict,
        motivo: 'Primera cita para probar conflicto',
      }),
    });

    assert.equal(firstResponse.status, 201);

    const conflictResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[1]!.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.backendConflict,
        motivo: 'Segunda cita en el mismo horario',
      }),
    });

    const conflictPayload = (await conflictResponse.json()) as { error?: string };

    assert.equal(conflictResponse.status, 409);
    assert.ok(conflictPayload.error?.includes('no tiene disponibilidad'));
  });
});

register('Portal paciente permite acceso, login, consulta y reserva de cita', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;
    const portalEmail = `portal.integration.${Date.now()}@dentaflow.local`;
    const portalPassword = 'portal123';

    await ensurePatientPortalAccess(client, patient.id, portalEmail, portalPassword);

    const session = await loginAsPatient(client, portalEmail, portalPassword);
    const authHeaders = {
      Authorization: `Bearer ${session.token}`,
    };

    const meResponse = await client.request('/api/patient-auth/me', {
      headers: authHeaders,
    });
    const mePayload = (await meResponse.json()) as {
      access?: {
        id: string;
      };
      patient?: {
        id: string;
      };
    };

    assert.equal(meResponse.status, 200);
    assert.equal(mePayload.access?.id, session.access.id);
    assert.equal(mePayload.patient?.id, patient.id);

    const profileResponse = await client.request('/api/patient-portal/profile', {
      headers: authHeaders,
    });
    const profilePayload = (await profileResponse.json()) as {
      patient?: {
        id: string;
        email: string | null;
      };
    };

    assert.equal(profileResponse.status, 200);
    assertDataSourceHeader(profileResponse);
    assert.equal(profilePayload.patient?.id, patient.id);

    const doctorsResponse = await client.request('/api/patient-portal/doctors', {
      headers: authHeaders,
    });
    const doctorsPayload = (await doctorsResponse.json()) as {
      doctors?: Array<{
        id: string;
        role: string;
      }>;
    };

    assert.equal(doctorsResponse.status, 200);
    assert.ok(Array.isArray(doctorsPayload.doctors));
    assert.ok(doctorsPayload.doctors?.some((doctor) => doctor.id === admin.id));

    const slotsResponse = await client.request('/api/patient-portal/doctors/' + admin.id + '/slots?date=2030-04-09', {
      headers: authHeaders,
    });
    const slotsPayload = (await slotsResponse.json()) as {
      date?: string;
      slots?: Array<{
        startAt: string;
      }>;
    };

    assert.equal(slotsResponse.status, 200);
    assert.equal(slotsPayload.date, '2030-04-09');
    assert.ok(slotsPayload.slots?.some((slot) => slot.startAt === '2030-04-09T15:00:00.000Z'));

    const appointmentResponse = await client.request('/api/patient-portal/appointments', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...authHeaders,
      },
      body: JSON.stringify({
        doctorUserId: admin.id,
        fecha: appointmentSlots.patientPortal,
        motivo: 'Reserva desde portal paciente',
      }),
    });

    const appointmentPayload = (await appointmentResponse.json()) as {
      appointment?: {
        id: string;
        fecha: string;
        motivo: string;
        dentista: {
          id: string;
        };
      };
      message?: string;
    };

    assert.equal(appointmentResponse.status, 201);
    assertDataSourceHeader(appointmentResponse);
    assert.ok(appointmentPayload.appointment?.id);
    assert.equal(appointmentPayload.appointment?.fecha, '2030-04-09T15:00:00.000Z');
    assert.equal(appointmentPayload.appointment?.motivo, 'Reserva desde portal paciente');
    assert.equal(appointmentPayload.appointment?.dentista.id, admin.id);
    assert.equal(appointmentPayload.message, 'Cita reservada correctamente.');

    const overviewResponse = await client.request('/api/patient-portal/overview', {
      headers: authHeaders,
    });
    const overviewPayload = (await overviewResponse.json()) as {
      overview?: {
        patient: {
          id: string;
        };
        appointments: Array<{
          id: string;
        }>;
      };
    };

    assert.equal(overviewResponse.status, 200);
    assert.equal(overviewPayload.overview?.patient.id, patient.id);
    assert.ok(
      overviewPayload.overview?.appointments.some(
        (appointment) => appointment.id === appointmentPayload.appointment?.id,
      ),
    );
  });
});

register('Portal doctor expone agenda, detalle y resumen clinico del paciente asignado', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;

    const appointmentCreateResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patient.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.doctorPortal,
        motivo: 'Reserva visible en portal doctor',
      }),
    });

    const createdAppointment = (await appointmentCreateResponse.json()) as {
      id: string;
    };

    assert.equal(appointmentCreateResponse.status, 201);

    const doctorHeaders = {
      'x-operational-user-id': admin.id,
    };

    const agendaResponse = await client.request('/api/doctor-mobile/agenda/upcoming', {
      headers: doctorHeaders,
    });
    const agendaPayload = (await agendaResponse.json()) as {
      doctor?: {
        id: string;
      };
      appointments?: Array<{
        id: string;
      }>;
    };

    assert.equal(agendaResponse.status, 200);
    assertDataSourceHeader(agendaResponse);
    assert.equal(agendaPayload.doctor?.id, admin.id);
    assert.ok(agendaPayload.appointments?.some((appointment) => appointment.id === createdAppointment.id));

    const detailResponse = await client.request(`/api/doctor-mobile/appointments/${createdAppointment.id}`, {
      headers: doctorHeaders,
    });
    const detailPayload = (await detailResponse.json()) as {
      appointment?: {
        id: string;
        paciente: {
          id: string;
        };
      };
    };

    assert.equal(detailResponse.status, 200);
    assert.equal(detailPayload.appointment?.id, createdAppointment.id);
    assert.equal(detailPayload.appointment?.paciente.id, patient.id);

    const summaryResponse = await client.request(`/api/doctor-mobile/patients/${patient.id}/summary`, {
      headers: doctorHeaders,
    });
    const summaryPayload = (await summaryResponse.json()) as {
      patient?: {
        id: string;
      };
      recentAppointments?: Array<{
        id: string;
      }>;
      metrics?: {
        upcomingAppointments: number;
      };
    };

    assert.equal(summaryResponse.status, 200);
    assertDataSourceHeader(summaryResponse);
    assert.equal(summaryPayload.patient?.id, patient.id);
    assert.ok(summaryPayload.metrics && summaryPayload.metrics.upcomingAppointments >= 1);
    assert.ok(summaryPayload.recentAppointments?.some((appointment) => appointment.id === createdAppointment.id));
  });
});

register('PUT /api/appointments reprograma la cita y agrega auditoria en notas', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 2);
    const patient = patients[1]!;
    const createResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patient.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.rescheduleOriginal,
        motivo: 'Cita para reprogramacion automatizada',
      }),
    });

    const createdAppointment = (await createResponse.json()) as {
      id: string;
    };

    assert.equal(createResponse.status, 201);

    const rescheduleReason = 'Paciente solicito mover la cita por trabajo';
    const updateResponse = await client.request(`/api/appointments/${createdAppointment.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        fecha: appointmentSlots.rescheduleUpdated,
        estado: 'CONFIRMADA',
        notas: 'Nota manual previa',
        rescheduleReason,
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      id: string;
      fecha: string;
      estado: string;
      notas: string | null;
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.id, createdAppointment.id);
    assert.equal(updatePayload.fecha, '2030-04-11T15:30:00.000Z');
    assert.equal(updatePayload.estado, 'CONFIRMADA');
    assert.ok(updatePayload.notas?.includes('Nota manual previa'));
    assert.ok(updatePayload.notas?.includes('[Reprogramacion'));
    assert.ok(updatePayload.notas?.includes(rescheduleReason));

    const doctorNotificationsAfter = await getDoctorNotifications(client, admin.id);
    assert.ok(
      doctorNotificationsAfter.notifications?.some(
        (notification) =>
          notification.title === 'Cita reprogramada' && notification.message.includes(rescheduleReason),
      ),
    );
  });
});

register('PUT /api/appointments rechaza reprogramar una cita a un horario ocupado', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 2);

    const firstResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[0]!.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.updateConflictFirst,
        motivo: 'Bloque ocupando horario para conflicto',
      }),
    });

    const firstAppointment = (await firstResponse.json()) as {
      id: string;
    };

    assert.equal(firstResponse.status, 201);
    assert.ok(firstAppointment.id);

    const secondResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[1]!.id,
        dentistaId: admin.id,
        fecha: appointmentSlots.updateConflictSecond,
        motivo: 'Cita que intentara reprogramarse al mismo horario',
      }),
    });

    const secondAppointment = (await secondResponse.json()) as {
      id: string;
    };

    assert.equal(secondResponse.status, 201);
    assert.ok(secondAppointment.id);

    const conflictUpdateResponse = await client.request(`/api/appointments/${secondAppointment.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        fecha: appointmentSlots.updateConflictFirst,
        rescheduleReason: 'Intento de choque de horario',
      }),
    });

    const conflictPayload = (await conflictUpdateResponse.json()) as { error?: string };

    assert.equal(conflictUpdateResponse.status, 409);
    assert.ok(conflictPayload.error?.includes('no tiene disponibilidad'));
  });
});

register('Portal paciente permite actualizar perfil y leer notificaciones de cita', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;
    const portalEmail = `portal.notifications.${Date.now()}@dentaflow.local`;
    const portalPassword = 'portal123';

    await ensurePatientPortalAccess(client, patient.id, portalEmail, portalPassword);
    const session = await loginAsPatient(client, portalEmail, portalPassword);

    const appointmentResponse = await client.request('/api/patient-portal/appointments', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${session.token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        doctorUserId: admin.id,
        fecha: '2030-04-13T09:00:00-05:00',
        motivo: 'Reserva para probar notificaciones del portal',
      }),
    });

    assert.equal(appointmentResponse.status, 201);

    const profileUpdateResponse = await client.request('/api/patient-portal/profile', {
      method: 'PUT',
      headers: {
        Authorization: `Bearer ${session.token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        telefono: '+51 900 111 222',
        direccion: 'Av. Pruebas 123',
      }),
    });

    const profileUpdatePayload = (await profileUpdateResponse.json()) as {
      patient?: {
        id: string;
        telefono: string | null;
        direccion: string | null;
      };
    };

    assert.equal(profileUpdateResponse.status, 200);
    assert.equal(profileUpdatePayload.patient?.id, patient.id);
    assert.equal(profileUpdatePayload.patient?.telefono, '+51 900 111 222');
    assert.equal(profileUpdatePayload.patient?.direccion, 'Av. Pruebas 123');

    const notificationsAfter = await getPatientPortalNotifications(client, session.token);

    const createdNotification = notificationsAfter.notifications?.find(
      (notification) =>
        notification.title === 'Tu cita fue agendada' &&
        notification.message.includes('Reserva para probar notificaciones del portal'),
    );

    assert.ok(createdNotification?.id);

    const readResponse = await client.request(
      `/api/patient-portal/notifications/${createdNotification?.id}/read`,
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${session.token}`,
        },
      },
    );

    const readPayload = (await readResponse.json()) as { ok?: boolean };
    assert.equal(readResponse.status, 200);
    assert.equal(readPayload.ok, true);

    const notificationsReadState = await getPatientPortalNotifications(client, session.token);
    const updatedNotification = notificationsReadState.notifications?.find(
      (notification) => notification.id === createdNotification?.id,
    );

    assert.ok(updatedNotification?.readAt);
  });
});

register('Portal doctor recibe notificaciones al crear nuevas citas', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 3);
    const uniqueMotivo = `Nueva cita para notificaciones doctor ${Date.now()}`;

    const createResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[2]!.id,
        dentistaId: admin.id,
        fecha: '2030-04-15T09:00:00-05:00',
        motivo: uniqueMotivo,
      }),
    });

    assert.equal(createResponse.status, 201);

    const doctorNotificationsAfter = await getDoctorNotifications(client, admin.id);
    assert.ok(
      doctorNotificationsAfter.notifications?.some(
        (notification) =>
          notification.title === 'Nueva cita asignada' && notification.message.includes(uniqueMotivo),
      ),
    );
  });
});

register('Pacientes permite crear, consultar y actualizar ficha clinica base', async () => {
  await withHttpClient(async (client) => {
    const uniqueSuffix = Date.now().toString();
    const dni = `9${uniqueSuffix.slice(-7)}`;
    const createResponse = await client.request('/api/patients', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dni,
        nombres: 'Paciente',
        apellidos: `QA ${uniqueSuffix}`,
        email: `patient.${uniqueSuffix}@dentaflow.local`,
        telefono: '+51 911 222 333',
        direccion: 'Av. Salud 100',
        alergias: 'Ninguna',
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
      dni?: string;
      nombres?: string;
      apellidos?: string;
      email?: string | null;
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.id);
    assert.equal(createPayload.dni, dni);
    assert.equal(createPayload.nombres, 'Paciente');
    assert.equal(createPayload.email, `patient.${uniqueSuffix}@dentaflow.local`);

    const duplicateResponse = await client.request('/api/patients', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dni,
        nombres: 'Duplicado',
        apellidos: 'Paciente',
      }),
    });

    const duplicatePayload = (await duplicateResponse.json()) as { error?: string };
    assert.equal(duplicateResponse.status, 409);
    assert.ok(duplicatePayload.error?.includes('documento'));

    const profileResponse = await client.request(`/api/patients/${createPayload.id}`);
    const profilePayload = (await profileResponse.json()) as {
      patient?: {
        id: string;
        dni: string;
        nombres: string;
        apellidos: string;
        nombreCompleto: string;
        direccion: string | null;
      };
      appointments?: unknown[];
      treatments?: unknown[];
      clinicalHistory?: {
        totalTreatments: number;
      };
      odontogram?: {
        pieces: unknown[];
      };
    };

    assert.equal(profileResponse.status, 200);
    assertDataSourceHeader(profileResponse);
    assert.equal(profilePayload.patient?.id, createPayload.id);
    assert.equal(profilePayload.patient?.nombreCompleto, `Paciente QA ${uniqueSuffix}`);
    assert.equal(profilePayload.patient?.direccion, 'Av. Salud 100');
    assert.equal(profilePayload.clinicalHistory?.totalTreatments, 0);
    assert.equal(profilePayload.odontogram?.pieces.length, 32);

    const updateResponse = await client.request(`/api/patients/${createPayload.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        telefono: '+51 944 555 666',
        direccion: 'Jr. Clinico 456',
        antecedentes: 'Sensibilidad dental',
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      id?: string;
      telefono?: string | null;
      direccion?: string | null;
      antecedentes?: string | null;
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.id, createPayload.id);
    assert.equal(updatePayload.telefono, '+51 944 555 666');
    assert.equal(updatePayload.direccion, 'Jr. Clinico 456');
    assert.equal(updatePayload.antecedentes, 'Sensibilidad dental');
  });
});

register('Archivo clinico del paciente responde aunque el fallback local este deshabilitado', async () => {
  await withHttpClient(async (client) => {
    const uniqueSuffix = Date.now().toString();
    const dni = `8${uniqueSuffix.slice(-7)}`;
    const createResponse = await client.request('/api/patients', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dni,
        nombres: 'Archivo',
        apellidos: `Clinico ${uniqueSuffix}`,
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
    };

    assert.equal(createResponse.status, 201);
    assert.ok(createPayload.id);

    const attachmentsResponse = await client.request(`/api/patients/${createPayload.id}/attachments`);
    const attachmentsPayload = (await attachmentsResponse.json()) as {
      attachments?: unknown[];
    };

    assert.equal(attachmentsResponse.status, 200);
    assert.equal(attachmentsResponse.headers.get('x-data-source'), 'local-fallback');
    assert.ok(Array.isArray(attachmentsPayload.attachments));
    assert.equal(attachmentsPayload.attachments?.length, 0);
  });
});

register('Tratamientos del paciente permiten alta y actualizacion', async () => {
  await withHttpClient(async (client) => {
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;
    const treatmentName = `Tratamiento QA ${Date.now()}`;

    const createResponse = await client.request(`/api/patients/${patient.id}/treatments`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        nombre: treatmentName,
        descripcion: 'Tratamiento creado desde integracion',
        costoBase: 320,
        estado: 'PLANIFICADO',
        piezaDental: '21',
        fechaInicio: '2030-05-01',
        notasClinicas: 'Paciente refiere molestia estetica',
        activo: true,
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
      nombre?: string;
      costoBase?: number;
      estado?: string;
      piezaDental?: string | null;
      notasClinicas?: string | null;
      activo?: boolean;
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.id);
    assert.equal(createPayload.nombre, treatmentName);
    assert.equal(createPayload.costoBase, 320);
    assert.equal(createPayload.estado, 'PLANIFICADO');
    assert.equal(createPayload.piezaDental, '21');
    assert.equal(createPayload.activo, true);

    const updateResponse = await client.request(`/api/patients/${patient.id}/treatments/${createPayload.id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        estado: 'EN_PROCESO',
        costoBase: 350,
        notasClinicas: 'Se inicio preparacion clinica',
        activo: false,
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      id?: string;
      estado?: string;
      costoBase?: number;
      notasClinicas?: string | null;
      activo?: boolean;
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.id, createPayload.id);
    assert.equal(updatePayload.estado, 'EN_PROCESO');
    assert.equal(updatePayload.costoBase, 350);
    assert.equal(updatePayload.notasClinicas, 'Se inicio preparacion clinica');
    assert.equal(updatePayload.activo, false);

    const profileResponse = await client.request(`/api/patients/${patient.id}`);
    const profilePayload = (await profileResponse.json()) as {
      treatments?: Array<{
        id: string;
        nombre: string;
        estado: string;
        costoBase: number;
      }>;
      clinicalHistory?: {
        totalTreatments: number;
      };
    };

    assert.equal(profileResponse.status, 200);
    assert.ok(
      profilePayload.treatments?.some(
        (treatment) =>
          treatment.id === createPayload.id &&
          treatment.nombre === treatmentName &&
          treatment.estado === 'EN_PROCESO' &&
          treatment.costoBase === 350,
      ),
    );
    assert.ok((profilePayload.clinicalHistory?.totalTreatments ?? 0) >= 1);
  });
});

register('Odontograma del paciente permite actualizar pieza y reflejar resumen clinico', async () => {
  await withHttpClient(async (client) => {
    const patients = await ensurePatients(client, 2);
    const patient = patients[1]!;

    const updateResponse = await client.request(`/api/patients/${patient.id}/odontogram/11`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        estado: 'IMPLANTE',
        caras: ['vestibular', 'palatino'],
        observacion: 'Pieza rehabilitada desde test',
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      numero?: number;
      estado?: string;
      caras?: string[];
      observacion?: string | null;
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.numero, 11);
    assert.equal(updatePayload.estado, 'IMPLANTE');
    assert.deepEqual(updatePayload.caras, ['vestibular', 'palatino']);
    assert.equal(updatePayload.observacion, 'Pieza rehabilitada desde test');

    const profileResponse = await client.request(`/api/patients/${patient.id}`);
    const profilePayload = (await profileResponse.json()) as {
      odontogram?: {
        summary: {
          affectedTeethCount: number;
          restoredCount: number;
        };
        pieces: Array<{
          numero: number;
          estado: string;
          caras: string[];
          observacion: string | null;
        }>;
      };
    };

    assert.equal(profileResponse.status, 200);
    const updatedPiece = profilePayload.odontogram?.pieces.find((piece) => piece.numero === 11);
    assert.equal(updatedPiece?.estado, 'IMPLANTE');
    assert.deepEqual(updatedPiece?.caras, ['vestibular', 'palatino']);
    assert.equal(updatedPiece?.observacion, 'Pieza rehabilitada desde test');
    assert.ok((profilePayload.odontogram?.summary.affectedTeethCount ?? 0) >= 1);
    assert.ok((profilePayload.odontogram?.summary.restoredCount ?? 0) >= 1);
  });
});

register('Presupuestos permite listar y crear documentos clinicos', async () => {
  await withHttpClient(async (client) => {
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;

    const listResponse = await client.request('/api/budgets');
    const listPayload = (await listResponse.json()) as Array<{
      id: string;
      folio: string;
      paciente: {
        id: string;
      };
    }>;

    assert.equal(listResponse.status, 200);
    assertDataSourceHeader(listResponse);
    assert.ok(Array.isArray(listPayload));

    const createResponse = await client.request('/api/budgets', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patient.id,
        total: 590,
        concepto: 'Plan integral QA',
        estado: 'PENDIENTE',
        tipoDocumento: 'BOLETA',
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
      folio?: string;
      total?: number;
      subtotal?: number;
      igv?: number;
      estado?: string;
      tipoDocumento?: string | null;
      concepto?: string;
      paciente?: {
        id: string;
      };
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.id);
    assert.match(createPayload.folio ?? '', /^[A-Z0-9]+-\d+$/);
    assert.equal(createPayload.total, 590);
    assert.equal(createPayload.estado, 'PENDIENTE');
    assert.equal(createPayload.tipoDocumento, 'BOLETA');
    assert.equal(createPayload.concepto, 'Plan integral QA');
    assert.equal(createPayload.paciente?.id, patient.id);
    assert.ok((createPayload.subtotal ?? 0) > 0);
    assert.ok((createPayload.igv ?? 0) > 0);
  });
});

register('Finanzas permite registrar movimientos y reflejar KPIs', async () => {
  await withHttpClient(async (client) => {
    const patients = await ensurePatients(client, 1);
    const patient = patients[0]!;

    const initialSummaryResponse = await client.request('/api/finances/summary');
    const initialSummaryPayload = (await initialSummaryResponse.json()) as {
      kpis?: {
        ingresos: number;
        egresos: number;
        balance: number;
      };
      transactions?: Array<{
        id: string;
      }>;
    };

    assert.equal(initialSummaryResponse.status, 200);
    assertDataSourceHeader(initialSummaryResponse);
    const ingresosIniciales = initialSummaryPayload.kpis?.ingresos ?? 0;
    const egresosIniciales = initialSummaryPayload.kpis?.egresos ?? 0;

    const ingresoResponse = await client.request('/api/finances/transactions', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        monto: 275,
        tipo: 'INGRESO',
        descripcion: 'Pago QA de control',
        pacienteId: patient.id,
      }),
    });

    const ingresoPayload = (await ingresoResponse.json()) as {
      id?: string;
      referencia?: string;
      monto?: number;
      tipo?: string;
      descripcion?: string;
      paciente?: {
        id: string;
      };
    };

    assert.equal(ingresoResponse.status, 201);
    assertDataSourceHeader(ingresoResponse);
    assert.ok(ingresoPayload.id);
    assert.match(ingresoPayload.referencia ?? '', /^[A-Z0-9]+-\d+$/);
    assert.equal(ingresoPayload.monto, 275);
    assert.equal(ingresoPayload.tipo, 'INGRESO');
    assert.equal(ingresoPayload.descripcion, 'Pago QA de control');
    assert.equal(ingresoPayload.paciente?.id, patient.id);

    const egresoResponse = await client.request('/api/finances/transactions', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        monto: 90,
        tipo: 'EGRESO',
        descripcion: 'Compra QA de insumos',
      }),
    });

    const egresoPayload = (await egresoResponse.json()) as {
      id?: string;
      tipo?: string;
      paciente?: {
        nombres: string;
      };
    };

    assert.equal(egresoResponse.status, 201);
    assertDataSourceHeader(egresoResponse);
    assert.ok(egresoPayload.id);
    assert.equal(egresoPayload.tipo, 'EGRESO');
    assert.equal(egresoPayload.paciente?.nombres, 'Caja');

    const finalSummaryResponse = await client.request('/api/finances/summary');
    const finalSummaryPayload = (await finalSummaryResponse.json()) as {
      kpis?: {
        ingresos: number;
        egresos: number;
        balance: number;
      };
      transactions?: Array<{
        id: string;
        descripcion: string;
      }>;
    };

    assert.equal(finalSummaryResponse.status, 200);
    assert.ok((finalSummaryPayload.kpis?.ingresos ?? 0) >= ingresosIniciales + 275);
    assert.ok((finalSummaryPayload.kpis?.egresos ?? 0) >= egresosIniciales + 90);
    assert.ok(
      finalSummaryPayload.transactions?.some((transaction) => transaction.id === ingresoPayload.id),
    );
    assert.ok(
      finalSummaryPayload.transactions?.some((transaction) => transaction.id === egresoPayload.id),
    );
  });
});

register('Inventario permite listar y registrar productos con validacion de codigo unico', async () => {
  await withHttpClient(async (client) => {
    const listResponse = await client.request('/api/inventory');
    const listPayload = (await listResponse.json()) as Array<{
      id: string;
      codigo: string;
    }>;

    assert.equal(listResponse.status, 200);
    assertDataSourceHeader(listResponse);
    assert.ok(Array.isArray(listPayload));

    const codigo = `INV-QA-${Date.now()}`;
    const createResponse = await client.request('/api/inventory', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        codigo,
        nombre: 'Composite QA',
        categoria: 'Restauracion',
        stockActual: 7,
        stockMinimo: 2,
        unidadMedida: 'unidad',
        costoUnitario: 44.5,
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
      codigo?: string;
      nombre?: string;
      stockActual?: number;
      stockMinimo?: number;
      costoUnitario?: number | null;
      activo?: boolean;
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.id);
    assert.equal(createPayload.codigo, codigo);
    assert.equal(createPayload.nombre, 'Composite QA');
    assert.equal(createPayload.stockActual, 7);
    assert.equal(createPayload.stockMinimo, 2);
    assert.equal(createPayload.costoUnitario, 44.5);
    assert.equal(createPayload.activo, true);

    const duplicateResponse = await client.request('/api/inventory', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        codigo,
        nombre: 'Duplicado QA',
        categoria: 'Restauracion',
        stockActual: 1,
        stockMinimo: 1,
        unidadMedida: 'unidad',
      }),
    });

    const duplicatePayload = (await duplicateResponse.json()) as { error?: string };
    assert.ok([409, 500].includes(duplicateResponse.status));
    assert.ok(duplicatePayload.error?.includes('codigo'));
  });
});

register('Recetas permite listar y crear prescripciones asociadas a pacientes', async () => {
  await withHttpClient(async (client) => {
    const patients = await ensurePatients(client, 2);
    const patient = patients[1]!;

    const listResponse = await client.request('/api/recipes');
    const listPayload = (await listResponse.json()) as Array<{
      id: string;
      codigo: string;
    }>;

    assert.equal(listResponse.status, 200);
    assertDataSourceHeader(listResponse);
    assert.ok(Array.isArray(listPayload));

    const createResponse = await client.request('/api/recipes', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patient.id,
        diagnostico: 'Dolor post procedimiento QA',
        indicaciones: 'Paracetamol 500mg cada 8 horas por 2 dias.',
        firmada: true,
      }),
    });

    const createPayload = (await createResponse.json()) as {
      id?: string;
      codigo?: string;
      diagnostico?: string;
      indicaciones?: string;
      firmada?: boolean;
      paciente?: {
        id: string;
      };
      medico?: {
        nombre: string;
      };
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.id);
    assert.match(createPayload.codigo ?? '', /^[A-Z0-9]+-\d+$/);
    assert.equal(createPayload.diagnostico, 'Dolor post procedimiento QA');
    assert.equal(createPayload.indicaciones, 'Paracetamol 500mg cada 8 horas por 2 dias.');
    assert.equal(createPayload.firmada, true);
    assert.equal(createPayload.paciente?.id, patient.id);
    assert.ok(typeof createPayload.medico?.nombre === 'string');

    const profileResponse = await client.request(`/api/patients/${patient.id}`);
    const profilePayload = (await profileResponse.json()) as {
      recipes?: Array<{
        id: string;
        diagnostico: string;
        firmada: boolean;
      }>;
      timeline?: Array<{
        id: string;
        type: string;
        title: string;
      }>;
    };

    assert.equal(profileResponse.status, 200);
    assert.ok(
      profilePayload.recipes?.some(
        (recipe) =>
          recipe.id === createPayload.id &&
          recipe.diagnostico === 'Dolor post procedimiento QA' &&
          recipe.firmada === true,
      ),
    );
    assert.ok(
      profilePayload.timeline?.some(
        (entry) => entry.type === 'recipe' && entry.title === 'Dolor post procedimiento QA',
      ),
    );
  });
});

register('Settings permite consultar y actualizar datos de la clinica', async () => {
  await withHttpClient(async (client) => {
    const { response: initialResponse, payload: initialPayload } = await getJson<{
      clinic?: {
        clinicName: string;
        location: string;
      };
      users?: Array<{
        id: string;
      }>;
    }>(client, '/api/settings');

    assert.equal(initialResponse.status, 200);
    assertDataSourceHeader(initialResponse);
    assert.equal(typeof initialPayload.clinic?.clinicName, 'string');
    assert.ok(Array.isArray(initialPayload.users));
    assert.ok((initialPayload.users?.length ?? 0) >= 1);

    const nextClinicName = `Clinica QA ${Date.now()}`;
    const updateResponse = await client.request('/api/settings/clinic', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        clinicName: nextClinicName,
        location: 'San Borja',
        contactPhone: '+51 955 000 111',
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      clinic?: {
        clinicName: string;
        location: string;
        contactPhone: string;
      };
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.clinic?.clinicName, nextClinicName);
    assert.equal(updatePayload.clinic?.location, 'San Borja');
    assert.equal(updatePayload.clinic?.contactPhone, '+51 955 000 111');

    const { response: refreshedResponse, payload: refreshedPayload } = await getJson<{
      clinic?: {
        clinicName: string;
        location: string;
        contactPhone: string;
      };
    }>(client, '/api/settings');

    assert.equal(refreshedResponse.status, 200);
    assert.equal(refreshedPayload.clinic?.clinicName, nextClinicName);
    assert.equal(refreshedPayload.clinic?.location, 'San Borja');
    assert.equal(refreshedPayload.clinic?.contactPhone, '+51 955 000 111');
  });
});

register('Settings permite crear usuarios y cambiar su contrasena', async () => {
  await withHttpClient(async (client) => {
    const uniqueSuffix = Date.now().toString();
    const email = `dentist.${uniqueSuffix}@dentaflow.local`;
    const originalPassword = 'dentist123';
    const changedPassword = 'dentist456';

    const createResponse = await client.request('/api/settings/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email,
        password: originalPassword,
        name: `Dentista QA ${uniqueSuffix}`,
        role: 'DENTIST',
      }),
    });

    const createPayload = (await createResponse.json()) as {
      user?: {
        id: string;
        email: string;
        role: string;
        active: boolean;
      };
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.ok(createPayload.user?.id);
    assert.equal(createPayload.user?.email, email);
    assert.equal(createPayload.user?.role, 'DENTIST');
    assert.equal(createPayload.user?.active, true);

    const duplicateResponse = await client.request('/api/settings/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email,
        password: originalPassword,
        name: 'Duplicado',
        role: 'DENTIST',
      }),
    });

    const duplicatePayload = (await duplicateResponse.json()) as { error?: string };
    assert.equal(duplicateResponse.status, 409);
    assert.equal(duplicatePayload.error, 'Ya existe un usuario con ese correo');

    const initialLogin = await loginWithCredentials(client, email, originalPassword);
    assert.equal(initialLogin.response.status, 200);
    assert.equal(initialLogin.payload.user?.email, email);

    const changeResponse = await client.request(`/api/settings/users/${createPayload.user?.id}/password/change`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        currentPassword: originalPassword,
        newPassword: changedPassword,
      }),
    });

    const changePayload = (await changeResponse.json()) as {
      message?: string;
      user?: {
        id: string;
      };
    };

    assert.equal(changeResponse.status, 200);
    assertDataSourceHeader(changeResponse);
    assert.equal(changePayload.user?.id, createPayload.user?.id);
    assert.equal(changePayload.message, 'Contrasena actualizada correctamente');

    const oldLogin = await loginWithCredentials(client, email, originalPassword);
    assert.equal(oldLogin.response.status, 401);
    assert.equal(oldLogin.payload.error, 'Credenciales invalidas');

    const newLogin = await loginWithCredentials(client, email, changedPassword);
    assert.equal(newLogin.response.status, 200);
    assert.equal(newLogin.payload.user?.id, createPayload.user?.id);
  });
});

register('Recuperacion publica y reseteo administrativo de contrasena funcionan', async () => {
  await withHttpClient(async (client) => {
    const uniqueSuffix = `${Date.now()}-recovery`;
    const email = `assistant.${uniqueSuffix}@dentaflow.local`;
    const originalPassword = 'recovery123';
    const recoveredPassword = 'recovery456';
    const resetPassword = 'recovery789';

    const createResponse = await client.request('/api/settings/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email,
        password: originalPassword,
        name: `Asistente QA ${uniqueSuffix}`,
        role: 'ADMIN',
      }),
    });

    const createPayload = (await createResponse.json()) as {
      user?: {
        id: string;
      };
    };

    assert.equal(createResponse.status, 201);
    assert.ok(createPayload.user?.id);

    const requestResponse = await client.request('/api/auth/recovery/request', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });

    const requestPayload = (await requestResponse.json()) as { message?: string };
    assert.equal(requestResponse.status, 200);
    assert.equal(
      requestPayload.message,
      'Si el correo existe, la solicitud fue registrada. Pide al administrador el codigo temporal desde Configuracion.',
    );

    const { response: pendingResponse, payload: pendingPayload } = await getJson<{
      requests?: Array<{
        id: string;
        userId: string;
        email: string;
        code: string;
      }>;
    }>(client, '/api/settings/password-recovery-requests');

    assert.equal(pendingResponse.status, 200);
    assertDataSourceHeader(pendingResponse);
    const recoveryRequest = pendingPayload.requests?.find((request) => request.email === email);
    assert.ok(recoveryRequest?.id);
    assert.equal(recoveryRequest?.userId, createPayload.user?.id);
    assert.match(recoveryRequest?.code ?? '', /^\d{6}$/);

    const completeResponse = await client.request('/api/auth/recovery/complete', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email,
        code: recoveryRequest?.code,
        newPassword: recoveredPassword,
      }),
    });

    const completePayload = (await completeResponse.json()) as { message?: string };
    assert.equal(completeResponse.status, 200);
    assert.equal(completePayload.message, 'Contrasena actualizada correctamente. Ya puedes iniciar sesion.');

    const recoveredLogin = await loginWithCredentials(client, email, recoveredPassword);
    assert.equal(recoveredLogin.response.status, 200);
    assert.equal(recoveredLogin.payload.user?.id, createPayload.user?.id);

    const { response: emptyRequestsResponse, payload: emptyRequestsPayload } = await getJson<{
      requests?: Array<{
        email: string;
      }>;
    }>(client, '/api/settings/password-recovery-requests');

    assert.equal(emptyRequestsResponse.status, 200);
    assert.equal(emptyRequestsPayload.requests?.some((request) => request.email === email), false);

    const resetResponse = await client.request(`/api/settings/users/${createPayload.user?.id}/password/reset`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        newPassword: resetPassword,
      }),
    });

    const resetPayload = (await resetResponse.json()) as {
      message?: string;
      user?: {
        id: string;
      };
    };

    assert.equal(resetResponse.status, 200);
    assertDataSourceHeader(resetResponse);
    assert.equal(resetPayload.user?.id, createPayload.user?.id);
    assert.equal(resetPayload.message, 'Contrasena restablecida correctamente');

    const oldRecoveredLogin = await loginWithCredentials(client, email, recoveredPassword);
    assert.equal(oldRecoveredLogin.response.status, 401);

    const resetLogin = await loginWithCredentials(client, email, resetPassword);
    assert.equal(resetLogin.response.status, 200);
    assert.equal(resetLogin.payload.user?.id, createPayload.user?.id);
  });
});

register('Settings de comunicaciones permite actualizar canales y consultar logs', async () => {
  await withHttpClient(async (client) => {
    const { response: initialResponse, payload: initialPayload } = await getJson<{
      settings?: {
        autoNotifyPatient: boolean;
        autoNotifyDentist: boolean;
        channels: {
          inApp: boolean;
          email: boolean;
          sms: boolean;
          whatsapp: boolean;
        };
        externalDeliveryMode: string;
        providerStatus: {
          inApp: {
            enabled: boolean;
          };
          email: {
            enabled: boolean;
          };
        };
      };
    }>(client, '/api/settings/communications');

    assert.equal(initialResponse.status, 200);
    assertDataSourceHeader(initialResponse);
    assert.equal(typeof initialPayload.settings?.autoNotifyPatient, 'boolean');
    assert.equal(typeof initialPayload.settings?.providerStatus.inApp.enabled, 'boolean');

    const updateResponse = await client.request('/api/settings/communications', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        autoNotifyPatient: true,
        autoNotifyDentist: true,
        channels: {
          inApp: true,
          email: false,
          sms: false,
          whatsapp: false,
        },
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      settings?: {
        autoNotifyPatient: boolean;
        autoNotifyDentist: boolean;
        channels: {
          inApp: boolean;
          email: boolean;
          sms: boolean;
          whatsapp: boolean;
        };
        externalDeliveryMode: string;
        providerStatus: {
          inApp: {
            enabled: boolean;
            mode: string;
          };
          email: {
            enabled: boolean;
          };
        };
      };
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.settings?.channels.inApp, true);
    assert.equal(updatePayload.settings?.channels.email, false);
    assert.equal(updatePayload.settings?.externalDeliveryMode, 'SIMULATED');
    assert.equal(updatePayload.settings?.providerStatus.inApp.enabled, true);
    assert.equal(updatePayload.settings?.providerStatus.email.enabled, false);

    const admin = await loginAsAdmin(client);
    const patients = await ensurePatients(client, 1);
    await ensurePatientPortalAccess(
      client,
      patients[0]!.id,
      `logs.patient.${Date.now()}@dentaflow.local`,
      'portal123',
    );
    const uniqueMotivo = `Logs comunicaciones ${Date.now()}`;
    const createResponse = await client.request('/api/appointments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        pacienteId: patients[0]!.id,
        dentistaId: admin.id,
        fecha: '2030-04-19T09:00:00-05:00',
        motivo: uniqueMotivo,
      }),
    });

    assert.equal(createResponse.status, 201);

    const { response: logsResponse, payload: logsPayload } = await getJson<{
      logs?: Array<{
        eventType: string;
        recipientRole: string;
        channel: string;
        title: string;
        message: string;
        status: string;
      }>;
    }>(client, '/api/settings/communications/logs?limit=50');

    assert.equal(logsResponse.status, 200);
    assertDataSourceHeader(logsResponse);
    const recentCreatedLogs =
      logsPayload.logs?.filter((log) => log.eventType === 'APPOINTMENT_CREATED').slice(0, 3) ?? [];

    assert.equal(recentCreatedLogs.length, 3);
    assert.ok(
      recentCreatedLogs.some(
        (log) =>
          log.eventType === 'APPOINTMENT_CREATED' &&
          log.recipientRole === 'PATIENT' &&
          log.channel === 'IN_APP' &&
          log.message.includes(uniqueMotivo),
      ),
    );
    assert.ok(
      recentCreatedLogs.some(
        (log) =>
          log.eventType === 'APPOINTMENT_CREATED' &&
          log.recipientRole === 'DENTIST' &&
          log.channel === 'IN_APP' &&
          log.message.includes(uniqueMotivo),
      ),
    );
    assert.ok(
      recentCreatedLogs.some(
        (log) =>
          log.eventType === 'APPOINTMENT_CREATED' &&
          log.recipientRole === 'SYSTEM' &&
          log.channel === 'IN_APP' &&
          log.title === 'Nueva cita registrada',
      ),
    );
  });
});

register('Horario semanal del doctor puede actualizarse y reflejarse en disponibilidad', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);

    const { response: scheduleResponse, payload: schedulePayload } = await getJson<{
      schedule?: Array<{
        dayOfWeek: number;
        isWorkingDay: boolean;
      }>;
    }>(client, `/api/settings/doctors/${admin.id}/schedule`);

    assert.equal(scheduleResponse.status, 200);
    assertDataSourceHeader(scheduleResponse);
    assert.equal(schedulePayload.schedule?.length, 7);

    const updateResponse = await client.request(`/api/settings/doctors/${admin.id}/schedule`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        schedule: [
          {
            dayOfWeek: 3,
            isWorkingDay: true,
            startTime: '08:00',
            endTime: '12:00',
            slotDurationMinutes: 45,
            breakStartTime: null,
            breakEndTime: null,
          },
        ],
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      schedule?: Array<{
        dayOfWeek: number;
        isWorkingDay: boolean;
        startTime: string | null;
        endTime: string | null;
        slotDurationMinutes: number;
      }>;
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    const updatedWednesday = updatePayload.schedule?.find((entry) => entry.dayOfWeek === 3);
    assert.equal(updatedWednesday?.isWorkingDay, true);
    assert.equal(updatedWednesday?.startTime, '08:00');
    assert.equal(updatedWednesday?.endTime, '12:00');
    assert.equal(updatedWednesday?.slotDurationMinutes, 45);

    const { response: slotsResponse, payload: slotsPayload } = await getJson<{
      date?: string;
      effectiveSchedule?: {
        isWorkingDay: boolean;
        startTime: string | null;
        endTime: string | null;
        slotDurationMinutes: number;
      };
      slots?: Array<{
        startAt: string;
      }>;
    }>(client, `/api/availability/doctors/${admin.id}/slots?date=${appointmentSlots.scheduleWeekly}`);

    assert.equal(slotsResponse.status, 200);
    assertDataSourceHeader(slotsResponse);
    assert.equal(slotsPayload.date, appointmentSlots.scheduleWeekly);
    assert.equal(slotsPayload.effectiveSchedule?.startTime, '08:00');
    assert.equal(slotsPayload.effectiveSchedule?.endTime, '12:00');
    assert.equal(slotsPayload.effectiveSchedule?.slotDurationMinutes, 45);
    assert.deepEqual(
      slotsPayload.slots?.slice(0, 4).map((slot) => slot.startAt),
      [
        '2030-04-17T13:00:00.000Z',
        '2030-04-17T13:45:00.000Z',
        '2030-04-17T14:30:00.000Z',
        '2030-04-17T15:15:00.000Z',
      ],
    );
  });
});

register('Overrides de horario del doctor permiten crear, actualizar y eliminar excepciones', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);

    const createResponse = await client.request(`/api/settings/doctors/${admin.id}/schedule-overrides`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dateKey: appointmentSlots.scheduleOverride,
        isWorkingDay: false,
        reason: 'Capacitacion interna',
      }),
    });

    const createPayload = (await createResponse.json()) as {
      override?: {
        dateKey: string;
        isWorkingDay: boolean;
        reason: string | null;
      };
    };

    assert.equal(createResponse.status, 201);
    assertDataSourceHeader(createResponse);
    assert.equal(createPayload.override?.dateKey, appointmentSlots.scheduleOverride);
    assert.equal(createPayload.override?.isWorkingDay, false);
    assert.equal(createPayload.override?.reason, 'Capacitacion interna');

    const duplicateResponse = await client.request(`/api/settings/doctors/${admin.id}/schedule-overrides`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        dateKey: appointmentSlots.scheduleOverride,
        isWorkingDay: false,
        reason: 'Duplicado',
      }),
    });

    const duplicatePayload = (await duplicateResponse.json()) as { error?: string };
    assert.equal(duplicateResponse.status, 409);
    assert.equal(duplicatePayload.error, 'Ya existe una excepcion configurada para esa fecha.');

    const { response: offSlotsResponse, payload: offSlotsPayload } = await getJson<{
      effectiveSchedule?: {
        isWorkingDay: boolean;
      };
      slots?: Array<{
        startAt: string;
      }>;
    }>(client, `/api/availability/doctors/${admin.id}/slots?date=${appointmentSlots.scheduleOverride}`);

    assert.equal(offSlotsResponse.status, 200);
    assert.equal(offSlotsPayload.effectiveSchedule?.isWorkingDay, false);
    assert.equal(offSlotsPayload.slots?.length, 0);

    const updateResponse = await client.request(
      `/api/settings/doctors/${admin.id}/schedule-overrides/${appointmentSlots.scheduleOverride}`,
      {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          isWorkingDay: true,
          startTime: '14:00',
          endTime: '16:00',
          slotDurationMinutes: 30,
          breakStartTime: '15:00',
          breakEndTime: '15:30',
          reason: 'Horario especial de tarde',
        }),
      },
    );

    const updatePayload = (await updateResponse.json()) as {
      override?: {
        dateKey: string;
        isWorkingDay: boolean;
        startTime: string | null;
        endTime: string | null;
        slotDurationMinutes: number | null;
        reason: string | null;
      };
    };

    assert.equal(updateResponse.status, 200);
    assertDataSourceHeader(updateResponse);
    assert.equal(updatePayload.override?.isWorkingDay, true);
    assert.equal(updatePayload.override?.startTime, '14:00');
    assert.equal(updatePayload.override?.endTime, '16:00');
    assert.equal(updatePayload.override?.slotDurationMinutes, 30);
    assert.equal(updatePayload.override?.reason, 'Horario especial de tarde');

    const { response: overridesResponse, payload: overridesPayload } = await getJson<{
      overrides?: Array<{
        dateKey: string;
        reason: string | null;
      }>;
    }>(
      client,
      `/api/settings/doctors/${admin.id}/schedule-overrides?dateFrom=${appointmentSlots.scheduleOverride}&dateTo=${appointmentSlots.scheduleOverride}`,
    );

    assert.equal(overridesResponse.status, 200);
    assertDataSourceHeader(overridesResponse);
    assert.ok(
      overridesPayload.overrides?.some(
        (override) =>
          override.dateKey === appointmentSlots.scheduleOverride &&
          override.reason === 'Horario especial de tarde',
      ),
    );

    const { response: customSlotsResponse, payload: customSlotsPayload } = await getJson<{
      effectiveSchedule?: {
        isWorkingDay: boolean;
        startTime: string | null;
        endTime: string | null;
        slotDurationMinutes: number;
      };
      slots?: Array<{
        startAt: string;
      }>;
    }>(client, `/api/availability/doctors/${admin.id}/slots?date=${appointmentSlots.scheduleOverride}`);

    assert.equal(customSlotsResponse.status, 200);
    assert.equal(customSlotsPayload.effectiveSchedule?.isWorkingDay, true);
    assert.equal(customSlotsPayload.effectiveSchedule?.startTime, '14:00');
    assert.equal(customSlotsPayload.effectiveSchedule?.endTime, '16:00');
    assert.equal(customSlotsPayload.effectiveSchedule?.slotDurationMinutes, 30);
    assert.deepEqual(
      customSlotsPayload.slots?.map((slot) => slot.startAt),
      ['2030-04-18T19:00:00.000Z', '2030-04-18T19:30:00.000Z', '2030-04-18T20:30:00.000Z'],
    );

    const deleteResponse = await client.request(
      `/api/settings/doctors/${admin.id}/schedule-overrides/${appointmentSlots.scheduleOverride}`,
      {
        method: 'DELETE',
      },
    );

    assert.equal(deleteResponse.status, 204);
    assertDataSourceHeader(deleteResponse);

    const { response: deletedOverridesResponse, payload: deletedOverridesPayload } = await getJson<{
      overrides?: Array<{
        dateKey: string;
      }>;
    }>(
      client,
      `/api/settings/doctors/${admin.id}/schedule-overrides?dateFrom=${appointmentSlots.scheduleOverride}&dateTo=${appointmentSlots.scheduleOverride}`,
    );

    assert.equal(deletedOverridesResponse.status, 200);
    assert.equal(
      deletedOverridesPayload.overrides?.some((override) => override.dateKey === appointmentSlots.scheduleOverride),
      false,
    );
  });
});

register('AgenteDental permite versionar y restaurar articulos', async () => {
  await withHttpClient(async (client) => {
    const admin = await loginAsAdmin(client);
    const adminHeaders = {
      'Content-Type': 'application/json',
      ...buildAdminSessionHeaders(admin),
    };
    const articleKey = Date.now().toString();
    const originalTitle = `Articulo AgenteDental ${articleKey}`;
    const originalAnswer = 'Version inicial del articulo.';
    const updatedAnswer = 'Version editada del articulo.';

    const createResponse = await client.request('/api/agent-dental/knowledge', {
      method: 'POST',
      headers: adminHeaders,
      body: JSON.stringify({
        title: originalTitle,
        summary: 'Version creada desde test',
        answer: originalAnswer,
        audience: ['staff'],
        keywords: ['versionado', 'restore'],
        steps: ['Paso inicial'],
        actions: [],
        relatedContextIds: ['testing'],
      }),
    });

    const createPayload = (await createResponse.json()) as {
      article?: {
        id: string;
        answer: string;
      };
    };

    assert.equal(createResponse.status, 201);
    assert.ok(createPayload.article?.id);
    assert.equal(createPayload.article?.answer, originalAnswer);

    const updateResponse = await client.request('/api/agent-dental/knowledge', {
      method: 'POST',
      headers: adminHeaders,
      body: JSON.stringify({
        id: createPayload.article?.id,
        title: originalTitle,
        summary: 'Version actualizada desde test',
        answer: updatedAnswer,
        audience: ['staff'],
        keywords: ['versionado', 'restore', 'updated'],
        steps: ['Paso actualizado'],
        actions: [],
        relatedContextIds: ['testing'],
      }),
    });

    const updatePayload = (await updateResponse.json()) as {
      article?: {
        id: string;
        answer: string;
      };
    };

    assert.equal(updateResponse.status, 201);
    assert.equal(updatePayload.article?.id, createPayload.article?.id);
    assert.equal(updatePayload.article?.answer, updatedAnswer);

    const versionsResponse = await client.request(
      `/api/agent-dental/knowledge/${createPayload.article?.id}/versions`,
      {
        headers: buildAdminSessionHeaders(admin),
      },
    );
    const versionsPayload = (await versionsResponse.json()) as {
      versions?: Array<{
        id: string;
        action: string;
        snapshot: {
          answer: string;
        };
      }>;
    };

    assert.equal(versionsResponse.status, 200);
    assertDataSourceHeader(versionsResponse);
    assert.ok(Array.isArray(versionsPayload.versions));
    assert.ok(versionsPayload.versions?.some((version) => version.action === 'CREATED'));
    assert.ok(versionsPayload.versions?.some((version) => version.action === 'UPDATED'));

    const createdVersion = versionsPayload.versions?.find((version) => version.action === 'CREATED');
    assert.ok(createdVersion?.id);

    const restoreResponse = await client.request(
      `/api/agent-dental/knowledge/${createPayload.article?.id}/restore/${createdVersion?.id}`,
      {
        method: 'POST',
        headers: buildAdminSessionHeaders(admin),
      },
    );
    const restorePayload = (await restoreResponse.json()) as {
      article?: {
        id: string;
        answer: string;
      };
    };

    assert.equal(restoreResponse.status, 200);
    assert.equal(restorePayload.article?.id, createPayload.article?.id);
    assert.equal(restorePayload.article?.answer, originalAnswer);

    const auditResponse = await client.request('/api/agent-dental/knowledge/audit?limit=10', {
      headers: buildAdminSessionHeaders(admin),
    });
    const auditPayload = (await auditResponse.json()) as {
      entries?: Array<{
        articleId: string;
        action: string;
      }>;
    };

    assert.equal(auditResponse.status, 200);
    assert.ok(
      auditPayload.entries?.some(
        (entry) => entry.articleId === createPayload.article?.id && entry.action === 'RESTORED',
      ),
    );
  });
});

const run = async () => {
  const snapshots = await captureDataSnapshots();
  let passed = 0;

  try {
    for (const currentTest of tests) {
      await currentTest.run();
      passed += 1;
      console.log(`PASS ${currentTest.name}`);
    }

    console.log(`OK ${passed}/${tests.length} pruebas`);
  } catch (error) {
    console.error(`FAIL ${tests[passed]?.name ?? 'suite'}`);
    console.error(error);
    process.exitCode = 1;
  } finally {
    await restoreDataSnapshots(snapshots);
    console.warn = originalConsoleWarn;
  }
};

void run();
