@blackcode_sa/metaestetics-api 1.12.7 → 1.12.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -794,49 +794,67 @@ var Language = /* @__PURE__ */ ((Language2) => {
794
794
  var ClinicTag = /* @__PURE__ */ ((ClinicTag6) => {
795
795
  ClinicTag6["PARKING"] = "parking";
796
796
  ClinicTag6["WIFI"] = "wifi";
797
- ClinicTag6["WHEELCHAIR_ACCESS"] = "wheelchair_access";
798
- ClinicTag6["CAFE"] = "cafe";
799
- ClinicTag6["PHARMACY"] = "pharmacy";
800
- ClinicTag6["WAITING_ROOM"] = "waiting_room";
797
+ ClinicTag6["LUXURY_WAITING"] = "luxury_waiting";
798
+ ClinicTag6["REFRESHMENTS"] = "refreshments";
799
+ ClinicTag6["PRIVATE_ROOMS"] = "private_rooms";
800
+ ClinicTag6["RECOVERY_AREA"] = "recovery_area";
801
801
  ClinicTag6["CARD_PAYMENT"] = "card_payment";
802
- ClinicTag6["INSURANCE"] = "insurance";
803
- ClinicTag6["CHILDREN_AREA"] = "children_area";
804
- ClinicTag6["TV"] = "tv";
805
- ClinicTag6["AIR_CONDITIONING"] = "air_conditioning";
806
- ClinicTag6["WATER_DISPENSER"] = "water_dispenser";
807
- ClinicTag6["VENDING_MACHINE"] = "vending_machine";
808
- ClinicTag6["ELEVATOR"] = "elevator";
809
- ClinicTag6["RAMP"] = "ramp";
810
- ClinicTag6["HANDICAP_PARKING"] = "handicap_parking";
811
- ClinicTag6["BRAILLE"] = "braille";
812
- ClinicTag6["SIGN_LANGUAGE"] = "sign_language";
813
- ClinicTag6["EMERGENCY_SERVICE"] = "emergency_service";
814
- ClinicTag6["LAB"] = "lab";
815
- ClinicTag6["XRAY"] = "xray";
816
- ClinicTag6["ULTRASOUND"] = "ultrasound";
817
- ClinicTag6["DENTAL"] = "dental";
818
- ClinicTag6["PEDIATRIC"] = "pediatric";
819
- ClinicTag6["GYNECOLOGY"] = "gynecology";
820
- ClinicTag6["CARDIOLOGY"] = "cardiology";
821
- ClinicTag6["DERMATOLOGY"] = "dermatology";
822
- ClinicTag6["ORTHOPEDIC"] = "orthopedic";
823
- ClinicTag6["OPHTHALMOLOGY"] = "ophthalmology";
824
- ClinicTag6["TELEMEDICINE"] = "telemedicine";
825
- ClinicTag6["HOME_VISITS"] = "home_visits";
802
+ ClinicTag6["FINANCING"] = "financing";
803
+ ClinicTag6["FREE_CONSULTATION"] = "free_consultation";
804
+ ClinicTag6["VIRTUAL_CONSULTATION"] = "virtual_consultation";
805
+ ClinicTag6["BEFORE_AFTER_PHOTOS"] = "before_after_photos";
806
+ ClinicTag6["AFTERCARE_SUPPORT"] = "aftercare_support";
807
+ ClinicTag6["BOTOX"] = "botox";
808
+ ClinicTag6["DERMAL_FILLERS"] = "dermal_fillers";
809
+ ClinicTag6["LASER_HAIR_REMOVAL"] = "laser_hair_removal";
810
+ ClinicTag6["LASER_SKIN_RESURFACING"] = "laser_skin_resurfacing";
811
+ ClinicTag6["CHEMICAL_PEELS"] = "chemical_peels";
812
+ ClinicTag6["MICRONEEDLING"] = "microneedling";
813
+ ClinicTag6["COOLSCULPTING"] = "coolsculpting";
814
+ ClinicTag6["THREAD_LIFT"] = "thread_lift";
815
+ ClinicTag6["LIP_ENHANCEMENT"] = "lip_enhancement";
816
+ ClinicTag6["RHINOPLASTY"] = "rhinoplasty";
817
+ ClinicTag6["SKIN_TIGHTENING"] = "skin_tightening";
818
+ ClinicTag6["FAT_DISSOLVING"] = "fat_dissolving";
819
+ ClinicTag6["PRP_TREATMENT"] = "prp_treatment";
820
+ ClinicTag6["HYDRAFACIAL"] = "hydrafacial";
821
+ ClinicTag6["IPL_PHOTOFACIAL"] = "ipl_photofacial";
822
+ ClinicTag6["BODY_CONTOURING"] = "body_contouring";
823
+ ClinicTag6["FACELIFT"] = "facelift";
824
+ ClinicTag6["RHINOPLASTY_SURGICAL"] = "rhinoplasty_surgical";
825
+ ClinicTag6["BREAST_AUGMENTATION"] = "breast_augmentation";
826
+ ClinicTag6["BREAST_REDUCTION"] = "breast_reduction";
827
+ ClinicTag6["BREAST_LIFT"] = "breast_lift";
828
+ ClinicTag6["TUMMY_TUCK"] = "tummy_tuck";
829
+ ClinicTag6["LIPOSUCTION"] = "liposuction";
830
+ ClinicTag6["BBL"] = "bbl";
831
+ ClinicTag6["MOMMY_MAKEOVER"] = "mommy_makeover";
832
+ ClinicTag6["ARM_LIFT"] = "arm_lift";
833
+ ClinicTag6["THIGH_LIFT"] = "thigh_lift";
834
+ ClinicTag6["EYELID_SURGERY"] = "eyelid_surgery";
835
+ ClinicTag6["BROW_LIFT"] = "brow_lift";
836
+ ClinicTag6["NECK_LIFT"] = "neck_lift";
837
+ ClinicTag6["OTOPLASTY"] = "otoplasty";
838
+ ClinicTag6["LABIAPLASTY"] = "labiaplasty";
826
839
  ClinicTag6["ONLINE_BOOKING"] = "online_booking";
827
840
  ClinicTag6["MOBILE_APP"] = "mobile_app";
828
841
  ClinicTag6["SMS_NOTIFICATIONS"] = "sms_notifications";
829
842
  ClinicTag6["EMAIL_NOTIFICATIONS"] = "email_notifications";
843
+ ClinicTag6["VIRTUAL_TRY_ON"] = "virtual_try_on";
844
+ ClinicTag6["SKIN_ANALYSIS"] = "skin_analysis";
845
+ ClinicTag6["TREATMENT_TRACKING"] = "treatment_tracking";
846
+ ClinicTag6["LOYALTY_PROGRAM"] = "loyalty_program";
830
847
  ClinicTag6["ENGLISH"] = "english";
831
- ClinicTag6["SERBIAN"] = "serbian";
832
848
  ClinicTag6["GERMAN"] = "german";
833
- ClinicTag6["RUSSIAN"] = "russian";
834
- ClinicTag6["CHINESE"] = "chinese";
835
- ClinicTag6["SPANISH"] = "spanish";
836
849
  ClinicTag6["FRENCH"] = "french";
850
+ ClinicTag6["SPANISH"] = "spanish";
851
+ ClinicTag6["ITALIAN"] = "italian";
852
+ ClinicTag6["DUTCH"] = "dutch";
853
+ ClinicTag6["RUSSIAN"] = "russian";
854
+ ClinicTag6["PORTUGUESE"] = "portuguese";
837
855
  ClinicTag6["OPEN_24_7"] = "open_24_7";
838
856
  ClinicTag6["WEEKEND_HOURS"] = "weekend_hours";
839
- ClinicTag6["NIGHT_SHIFT"] = "night_shift";
857
+ ClinicTag6["EXTENDED_HOURS"] = "extended_hours";
840
858
  ClinicTag6["HOLIDAY_HOURS"] = "holiday_hours";
841
859
  return ClinicTag6;
842
860
  })(ClinicTag || {});
@@ -1172,24 +1190,18 @@ var AppointmentService = class extends BaseService {
1172
1190
  `[APPOINTMENT_SERVICE] Getting available booking slots via HTTP for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
1173
1191
  );
1174
1192
  if (!clinicId || !practitionerId || !procedureId || !startDate || !endDate) {
1175
- throw new Error(
1176
- "Missing required parameters for booking slots calculation"
1177
- );
1193
+ throw new Error("Missing required parameters for booking slots calculation");
1178
1194
  }
1179
1195
  if (endDate <= startDate) {
1180
1196
  throw new Error("End date must be after start date");
1181
1197
  }
1182
1198
  const currentUser = this.auth.currentUser;
1183
1199
  if (!currentUser) {
1184
- throw new Error(
1185
- "User must be authenticated to get available booking slots"
1186
- );
1200
+ throw new Error("User must be authenticated to get available booking slots");
1187
1201
  }
1188
1202
  const functionUrl = `https://europe-west6-metaestetics.cloudfunctions.net/bookingApi/getAvailableBookingSlots`;
1189
1203
  const idToken = await currentUser.getIdToken();
1190
- console.log(
1191
- `[APPOINTMENT_SERVICE] Got user token, user ID: ${currentUser.uid}`
1192
- );
1204
+ console.log(`[APPOINTMENT_SERVICE] Got user token, user ID: ${currentUser.uid}`);
1193
1205
  const requestData = {
1194
1206
  clinicId,
1195
1207
  practitionerId,
@@ -1200,9 +1212,7 @@ var AppointmentService = class extends BaseService {
1200
1212
  end: endDate.getTime()
1201
1213
  }
1202
1214
  };
1203
- console.log(
1204
- `[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
1205
- );
1215
+ console.log(`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`);
1206
1216
  const response = await fetch(functionUrl, {
1207
1217
  method: "POST",
1208
1218
  mode: "cors",
@@ -1224,9 +1234,7 @@ var AppointmentService = class extends BaseService {
1224
1234
  );
1225
1235
  if (!response.ok) {
1226
1236
  const errorText = await response.text();
1227
- console.error(
1228
- `[APPOINTMENT_SERVICE] Error response details: ${errorText}`
1229
- );
1237
+ console.error(`[APPOINTMENT_SERVICE] Error response details: ${errorText}`);
1230
1238
  throw new Error(
1231
1239
  `Failed to get available booking slots: ${response.status} ${response.statusText} - ${errorText}`
1232
1240
  );
@@ -1234,24 +1242,15 @@ var AppointmentService = class extends BaseService {
1234
1242
  const result = await response.json();
1235
1243
  console.log(`[APPOINTMENT_SERVICE] Response parsed successfully`, result);
1236
1244
  if (!result.success) {
1237
- throw new Error(
1238
- result.error || "Failed to get available booking slots"
1239
- );
1245
+ throw new Error(result.error || "Failed to get available booking slots");
1240
1246
  }
1241
- const slots = result.availableSlots.map(
1242
- (slot) => ({
1243
- start: new Date(slot.start)
1244
- })
1245
- );
1246
- console.log(
1247
- `[APPOINTMENT_SERVICE] Found ${slots.length} available booking slots via HTTP`
1248
- );
1247
+ const slots = result.availableSlots.map((slot) => ({
1248
+ start: new Date(slot.start)
1249
+ }));
1250
+ console.log(`[APPOINTMENT_SERVICE] Found ${slots.length} available booking slots via HTTP`);
1249
1251
  return slots;
1250
1252
  } catch (error) {
1251
- console.error(
1252
- "[APPOINTMENT_SERVICE] Error getting available booking slots via HTTP:",
1253
- error
1254
- );
1253
+ console.error("[APPOINTMENT_SERVICE] Error getting available booking slots via HTTP:", error);
1255
1254
  throw error;
1256
1255
  }
1257
1256
  }
@@ -1263,9 +1262,7 @@ var AppointmentService = class extends BaseService {
1263
1262
  */
1264
1263
  async createAppointmentHttp(data) {
1265
1264
  try {
1266
- console.log(
1267
- "[APPOINTMENT_SERVICE] Creating appointment via cloud function"
1268
- );
1265
+ console.log("[APPOINTMENT_SERVICE] Creating appointment via cloud function");
1269
1266
  const currentUser = this.auth.currentUser;
1270
1267
  if (!currentUser) {
1271
1268
  throw new Error("User must be authenticated to create an appointment");
@@ -1279,9 +1276,7 @@ var AppointmentService = class extends BaseService {
1279
1276
  appointmentEndTime: data.appointmentEndTime.toMillis ? data.appointmentEndTime.toMillis() : new Date(data.appointmentEndTime).getTime(),
1280
1277
  patientNotes: (data == null ? void 0 : data.patientNotes) || null
1281
1278
  };
1282
- console.log(
1283
- `[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
1284
- );
1279
+ console.log(`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`);
1285
1280
  const response = await fetch(functionUrl, {
1286
1281
  method: "POST",
1287
1282
  mode: "cors",
@@ -1300,9 +1295,7 @@ var AppointmentService = class extends BaseService {
1300
1295
  );
1301
1296
  if (!response.ok) {
1302
1297
  const errorText = await response.text();
1303
- console.error(
1304
- `[APPOINTMENT_SERVICE] Error response details: ${errorText}`
1305
- );
1298
+ console.error(`[APPOINTMENT_SERVICE] Error response details: ${errorText}`);
1306
1299
  throw new Error(
1307
1300
  `Failed to create appointment: ${response.status} ${response.statusText} - ${errorText}`
1308
1301
  );
@@ -1312,25 +1305,16 @@ var AppointmentService = class extends BaseService {
1312
1305
  throw new Error(result.error || "Failed to create appointment");
1313
1306
  }
1314
1307
  if (result.appointmentData) {
1315
- console.log(
1316
- `[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`
1317
- );
1308
+ console.log(`[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`);
1318
1309
  return result.appointmentData;
1319
1310
  }
1320
- const createdAppointment = await this.getAppointmentById(
1321
- result.appointmentId
1322
- );
1311
+ const createdAppointment = await this.getAppointmentById(result.appointmentId);
1323
1312
  if (!createdAppointment) {
1324
- throw new Error(
1325
- `Failed to retrieve created appointment with ID: ${result.appointmentId}`
1326
- );
1313
+ throw new Error(`Failed to retrieve created appointment with ID: ${result.appointmentId}`);
1327
1314
  }
1328
1315
  return createdAppointment;
1329
1316
  } catch (error) {
1330
- console.error(
1331
- "[APPOINTMENT_SERVICE] Error creating appointment via cloud function:",
1332
- error
1333
- );
1317
+ console.error("[APPOINTMENT_SERVICE] Error creating appointment via cloud function:", error);
1334
1318
  throw error;
1335
1319
  }
1336
1320
  }
@@ -1342,19 +1326,14 @@ var AppointmentService = class extends BaseService {
1342
1326
  */
1343
1327
  async getAppointmentById(appointmentId) {
1344
1328
  try {
1345
- console.log(
1346
- `[APPOINTMENT_SERVICE] Getting appointment with ID: ${appointmentId}`
1347
- );
1329
+ console.log(`[APPOINTMENT_SERVICE] Getting appointment with ID: ${appointmentId}`);
1348
1330
  const appointment = await getAppointmentByIdUtil(this.db, appointmentId);
1349
1331
  console.log(
1350
1332
  `[APPOINTMENT_SERVICE] Appointment ${appointmentId} ${appointment ? "found" : "not found"}`
1351
1333
  );
1352
1334
  return appointment;
1353
1335
  } catch (error) {
1354
- console.error(
1355
- `[APPOINTMENT_SERVICE] Error getting appointment ${appointmentId}:`,
1356
- error
1357
- );
1336
+ console.error(`[APPOINTMENT_SERVICE] Error getting appointment ${appointmentId}:`, error);
1358
1337
  throw error;
1359
1338
  }
1360
1339
  }
@@ -1367,24 +1346,13 @@ var AppointmentService = class extends BaseService {
1367
1346
  */
1368
1347
  async updateAppointment(appointmentId, data) {
1369
1348
  try {
1370
- console.log(
1371
- `[APPOINTMENT_SERVICE] Updating appointment with ID: ${appointmentId}`
1372
- );
1349
+ console.log(`[APPOINTMENT_SERVICE] Updating appointment with ID: ${appointmentId}`);
1373
1350
  const validatedData = await updateAppointmentSchema.parseAsync(data);
1374
- const updatedAppointment = await updateAppointmentUtil(
1375
- this.db,
1376
- appointmentId,
1377
- validatedData
1378
- );
1379
- console.log(
1380
- `[APPOINTMENT_SERVICE] Appointment ${appointmentId} updated successfully`
1381
- );
1351
+ const updatedAppointment = await updateAppointmentUtil(this.db, appointmentId, validatedData);
1352
+ console.log(`[APPOINTMENT_SERVICE] Appointment ${appointmentId} updated successfully`);
1382
1353
  return updatedAppointment;
1383
1354
  } catch (error) {
1384
- console.error(
1385
- `[APPOINTMENT_SERVICE] Error updating appointment ${appointmentId}:`,
1386
- error
1387
- );
1355
+ console.error(`[APPOINTMENT_SERVICE] Error updating appointment ${appointmentId}:`, error);
1388
1356
  throw error;
1389
1357
  }
1390
1358
  }
@@ -1396,21 +1364,13 @@ var AppointmentService = class extends BaseService {
1396
1364
  */
1397
1365
  async searchAppointments(params) {
1398
1366
  try {
1399
- console.log(
1400
- "[APPOINTMENT_SERVICE] Searching appointments with params:",
1401
- params
1402
- );
1367
+ console.log("[APPOINTMENT_SERVICE] Searching appointments with params:", params);
1403
1368
  await searchAppointmentsSchema.parseAsync(params);
1404
1369
  const result = await searchAppointmentsUtil(this.db, params);
1405
- console.log(
1406
- `[APPOINTMENT_SERVICE] Found ${result.appointments.length} appointments`
1407
- );
1370
+ console.log(`[APPOINTMENT_SERVICE] Found ${result.appointments.length} appointments`);
1408
1371
  return result;
1409
1372
  } catch (error) {
1410
- console.error(
1411
- "[APPOINTMENT_SERVICE] Error searching appointments:",
1412
- error
1413
- );
1373
+ console.error("[APPOINTMENT_SERVICE] Error searching appointments:", error);
1414
1374
  throw error;
1415
1375
  }
1416
1376
  }
@@ -1422,9 +1382,7 @@ var AppointmentService = class extends BaseService {
1422
1382
  * @returns Found appointments and the last document for pagination
1423
1383
  */
1424
1384
  async getPatientAppointments(patientId, options) {
1425
- console.log(
1426
- `[APPOINTMENT_SERVICE] Getting appointments for patient: ${patientId}`
1427
- );
1385
+ console.log(`[APPOINTMENT_SERVICE] Getting appointments for patient: ${patientId}`);
1428
1386
  const searchParams = {
1429
1387
  patientId,
1430
1388
  startDate: options == null ? void 0 : options.startDate,
@@ -1443,9 +1401,7 @@ var AppointmentService = class extends BaseService {
1443
1401
  * @returns Found appointments and the last document for pagination
1444
1402
  */
1445
1403
  async getPractitionerAppointments(practitionerId, options) {
1446
- console.log(
1447
- `[APPOINTMENT_SERVICE] Getting appointments for practitioner: ${practitionerId}`
1448
- );
1404
+ console.log(`[APPOINTMENT_SERVICE] Getting appointments for practitioner: ${practitionerId}`);
1449
1405
  const searchParams = {
1450
1406
  practitionerId,
1451
1407
  startDate: options == null ? void 0 : options.startDate,
@@ -1464,9 +1420,7 @@ var AppointmentService = class extends BaseService {
1464
1420
  * @returns Found appointments and the last document for pagination
1465
1421
  */
1466
1422
  async getClinicAppointments(clinicBranchId, options) {
1467
- console.log(
1468
- `[APPOINTMENT_SERVICE] Getting appointments for clinic: ${clinicBranchId}`
1469
- );
1423
+ console.log(`[APPOINTMENT_SERVICE] Getting appointments for clinic: ${clinicBranchId}`);
1470
1424
  const searchParams = {
1471
1425
  clinicBranchId,
1472
1426
  practitionerId: options == null ? void 0 : options.practitionerId,
@@ -1517,68 +1471,42 @@ var AppointmentService = class extends BaseService {
1517
1471
  * Confirms a PENDING appointment by an Admin/Clinic.
1518
1472
  */
1519
1473
  async confirmAppointmentAdmin(appointmentId) {
1520
- console.log(
1521
- `[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`
1522
- );
1474
+ console.log(`[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`);
1523
1475
  const appointment = await this.getAppointmentById(appointmentId);
1524
- if (!appointment)
1525
- throw new Error(`Appointment ${appointmentId} not found.`);
1476
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1526
1477
  if (appointment.status !== "pending" /* PENDING */) {
1527
- throw new Error(
1528
- `Appointment ${appointmentId} is not in PENDING state to be confirmed.`
1529
- );
1478
+ throw new Error(`Appointment ${appointmentId} is not in PENDING state to be confirmed.`);
1530
1479
  }
1531
- return this.updateAppointmentStatus(
1532
- appointmentId,
1533
- "confirmed" /* CONFIRMED */
1534
- );
1480
+ return this.updateAppointmentStatus(appointmentId, "confirmed" /* CONFIRMED */);
1535
1481
  }
1536
1482
  /**
1537
1483
  * Cancels an appointment by the User (Patient).
1538
1484
  */
1539
1485
  async cancelAppointmentUser(appointmentId, reason) {
1540
- console.log(
1541
- `[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`
1542
- );
1543
- return this.updateAppointmentStatus(
1544
- appointmentId,
1545
- "canceled_patient" /* CANCELED_PATIENT */,
1546
- {
1547
- cancellationReason: reason,
1548
- canceledBy: "patient"
1549
- }
1550
- );
1486
+ console.log(`[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`);
1487
+ return this.updateAppointmentStatus(appointmentId, "canceled_patient" /* CANCELED_PATIENT */, {
1488
+ cancellationReason: reason,
1489
+ canceledBy: "patient"
1490
+ });
1551
1491
  }
1552
1492
  /**
1553
1493
  * Cancels an appointment by an Admin/Clinic.
1554
1494
  */
1555
1495
  async cancelAppointmentAdmin(appointmentId, reason) {
1556
- console.log(
1557
- `[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`
1558
- );
1559
- return this.updateAppointmentStatus(
1560
- appointmentId,
1561
- "canceled_clinic" /* CANCELED_CLINIC */,
1562
- {
1563
- cancellationReason: reason,
1564
- canceledBy: "clinic"
1565
- }
1566
- );
1496
+ console.log(`[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`);
1497
+ return this.updateAppointmentStatus(appointmentId, "canceled_clinic" /* CANCELED_CLINIC */, {
1498
+ cancellationReason: reason,
1499
+ canceledBy: "clinic"
1500
+ });
1567
1501
  }
1568
1502
  /**
1569
1503
  * Admin proposes to reschedule an appointment.
1570
1504
  * Sets status to RESCHEDULED_BY_CLINIC and updates times.
1571
1505
  */
1572
1506
  async rescheduleAppointmentAdmin(params) {
1573
- console.log(
1574
- `[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`
1575
- );
1576
- const validatedParams = await rescheduleAppointmentSchema.parseAsync(
1577
- params
1578
- );
1579
- const startTimestamp = this.convertToTimestamp(
1580
- validatedParams.newStartTime
1581
- );
1507
+ console.log(`[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`);
1508
+ const validatedParams = await rescheduleAppointmentSchema.parseAsync(params);
1509
+ const startTimestamp = this.convertToTimestamp(validatedParams.newStartTime);
1582
1510
  const endTimestamp = this.convertToTimestamp(validatedParams.newEndTime);
1583
1511
  if (endTimestamp.toMillis() <= startTimestamp.toMillis()) {
1584
1512
  throw new Error("New end time must be after new start time.");
@@ -1621,48 +1549,31 @@ var AppointmentService = class extends BaseService {
1621
1549
  if (value && typeof value.seconds === "number") {
1622
1550
  return new import_firestore2.Timestamp(value.seconds, value.nanoseconds || 0);
1623
1551
  }
1624
- throw new Error(
1625
- `Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(
1626
- value
1627
- )}`
1628
- );
1552
+ throw new Error(`Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(value)}`);
1629
1553
  }
1630
1554
  /**
1631
1555
  * User confirms a reschedule proposed by the clinic.
1632
1556
  * Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
1633
1557
  */
1634
1558
  async rescheduleAppointmentConfirmUser(appointmentId) {
1635
- console.log(
1636
- `[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`
1637
- );
1559
+ console.log(`[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`);
1638
1560
  const appointment = await this.getAppointmentById(appointmentId);
1639
- if (!appointment)
1640
- throw new Error(`Appointment ${appointmentId} not found.`);
1561
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1641
1562
  if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
1642
- throw new Error(
1643
- `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
1644
- );
1563
+ throw new Error(`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`);
1645
1564
  }
1646
- return this.updateAppointmentStatus(
1647
- appointmentId,
1648
- "confirmed" /* CONFIRMED */
1649
- );
1565
+ return this.updateAppointmentStatus(appointmentId, "confirmed" /* CONFIRMED */);
1650
1566
  }
1651
1567
  /**
1652
1568
  * User rejects a reschedule proposed by the clinic.
1653
1569
  * Status changes from RESCHEDULED_BY_CLINIC to CANCELED_PATIENT_RESCHEDULED.
1654
1570
  */
1655
1571
  async rescheduleAppointmentRejectUser(appointmentId, reason) {
1656
- console.log(
1657
- `[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`
1658
- );
1572
+ console.log(`[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`);
1659
1573
  const appointment = await this.getAppointmentById(appointmentId);
1660
- if (!appointment)
1661
- throw new Error(`Appointment ${appointmentId} not found.`);
1574
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1662
1575
  if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
1663
- throw new Error(
1664
- `Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
1665
- );
1576
+ throw new Error(`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`);
1666
1577
  }
1667
1578
  return this.updateAppointmentStatus(
1668
1579
  appointmentId,
@@ -1678,17 +1589,12 @@ var AppointmentService = class extends BaseService {
1678
1589
  * Requires all pending user forms to be completed.
1679
1590
  */
1680
1591
  async checkInPatientAdmin(appointmentId) {
1681
- console.log(
1682
- `[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`
1683
- );
1592
+ console.log(`[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`);
1684
1593
  const appointment = await this.getAppointmentById(appointmentId);
1685
- if (!appointment)
1686
- throw new Error(`Appointment ${appointmentId} not found.`);
1594
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1687
1595
  if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.length > 0) {
1688
1596
  throw new Error(
1689
- `Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(
1690
- ", "
1691
- )}`
1597
+ `Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(", ")}`
1692
1598
  );
1693
1599
  }
1694
1600
  if (appointment.status !== "confirmed" /* CONFIRMED */ && appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
@@ -1696,25 +1602,17 @@ var AppointmentService = class extends BaseService {
1696
1602
  `Checking in appointment ${appointmentId} with status ${appointment.status}. Ensure this is intended.`
1697
1603
  );
1698
1604
  }
1699
- return this.updateAppointmentStatus(
1700
- appointmentId,
1701
- "checked_in" /* CHECKED_IN */
1702
- );
1605
+ return this.updateAppointmentStatus(appointmentId, "checked_in" /* CHECKED_IN */);
1703
1606
  }
1704
1607
  /**
1705
1608
  * Doctor starts the appointment procedure.
1706
1609
  */
1707
1610
  async startAppointmentDoctor(appointmentId) {
1708
- console.log(
1709
- `[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`
1710
- );
1611
+ console.log(`[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`);
1711
1612
  const appointment = await this.getAppointmentById(appointmentId);
1712
- if (!appointment)
1713
- throw new Error(`Appointment ${appointmentId} not found.`);
1613
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1714
1614
  if (appointment.status !== "checked_in" /* CHECKED_IN */) {
1715
- throw new Error(
1716
- `Appointment ${appointmentId} must be CHECKED_IN to start.`
1717
- );
1615
+ throw new Error(`Appointment ${appointmentId} must be CHECKED_IN to start.`);
1718
1616
  }
1719
1617
  const updateData = {
1720
1618
  status: "in_progress" /* IN_PROGRESS */,
@@ -1728,24 +1626,18 @@ var AppointmentService = class extends BaseService {
1728
1626
  * Doctor completes and finalizes the appointment.
1729
1627
  */
1730
1628
  async completeAppointmentDoctor(appointmentId, finalizationNotes, actualDurationMinutesInput) {
1731
- console.log(
1732
- `[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`
1733
- );
1629
+ console.log(`[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`);
1734
1630
  const currentUser = this.auth.currentUser;
1735
- if (!currentUser)
1736
- throw new Error("Authentication required to complete appointment.");
1631
+ if (!currentUser) throw new Error("Authentication required to complete appointment.");
1737
1632
  const appointment = await this.getAppointmentById(appointmentId);
1738
- if (!appointment)
1739
- throw new Error(`Appointment ${appointmentId} not found.`);
1633
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1740
1634
  let calculatedDurationMinutes = actualDurationMinutesInput;
1741
1635
  const procedureCompletionTime = import_firestore2.Timestamp.now();
1742
1636
  if (calculatedDurationMinutes === void 0 && appointment.procedureActualStartTime) {
1743
1637
  const startTimeMillis = appointment.procedureActualStartTime.toMillis();
1744
1638
  const endTimeMillis = procedureCompletionTime.toMillis();
1745
1639
  if (endTimeMillis > startTimeMillis) {
1746
- calculatedDurationMinutes = Math.round(
1747
- (endTimeMillis - startTimeMillis) / 6e4
1748
- );
1640
+ calculatedDurationMinutes = Math.round((endTimeMillis - startTimeMillis) / 6e4);
1749
1641
  }
1750
1642
  }
1751
1643
  const updateData = {
@@ -1769,31 +1661,22 @@ var AppointmentService = class extends BaseService {
1769
1661
  * Admin marks an appointment as No-Show.
1770
1662
  */
1771
1663
  async markNoShowAdmin(appointmentId) {
1772
- console.log(
1773
- `[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`
1774
- );
1664
+ console.log(`[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`);
1775
1665
  const appointment = await this.getAppointmentById(appointmentId);
1776
- if (!appointment)
1777
- throw new Error(`Appointment ${appointmentId} not found.`);
1666
+ if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
1778
1667
  if (import_firestore2.Timestamp.now().toMillis() < appointment.appointmentStartTime.toMillis()) {
1779
1668
  throw new Error("Cannot mark no-show before appointment start time.");
1780
1669
  }
1781
- return this.updateAppointmentStatus(
1782
- appointmentId,
1783
- "no_show" /* NO_SHOW */,
1784
- {
1785
- cancellationReason: "Patient did not show up for the appointment.",
1786
- canceledBy: "clinic"
1787
- }
1788
- );
1670
+ return this.updateAppointmentStatus(appointmentId, "no_show" /* NO_SHOW */, {
1671
+ cancellationReason: "Patient did not show up for the appointment.",
1672
+ canceledBy: "clinic"
1673
+ });
1789
1674
  }
1790
1675
  /**
1791
1676
  * Adds a media item to an appointment.
1792
1677
  */
1793
1678
  async addMediaToAppointment(appointmentId, mediaItemData) {
1794
- console.log(
1795
- `[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`
1796
- );
1679
+ console.log(`[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`);
1797
1680
  const currentUser = this.auth.currentUser;
1798
1681
  if (!currentUser) throw new Error("Authentication required.");
1799
1682
  const newMediaItem = {
@@ -1833,9 +1716,7 @@ var AppointmentService = class extends BaseService {
1833
1716
  * Adds or updates review information for an appointment.
1834
1717
  */
1835
1718
  async addReviewToAppointment(appointmentId, reviewData) {
1836
- console.log(
1837
- `[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`
1838
- );
1719
+ console.log(`[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`);
1839
1720
  const newReviewInfo = {
1840
1721
  ...reviewData,
1841
1722
  reviewId: this.generateId(),
@@ -1869,9 +1750,7 @@ var AppointmentService = class extends BaseService {
1869
1750
  * @returns The updated appointment
1870
1751
  */
1871
1752
  async updateInternalNotes(appointmentId, notes) {
1872
- console.log(
1873
- `[APPOINTMENT_SERVICE] Updating internal notes for appointment: ${appointmentId}`
1874
- );
1753
+ console.log(`[APPOINTMENT_SERVICE] Updating internal notes for appointment: ${appointmentId}`);
1875
1754
  const updateData = {
1876
1755
  internalNotes: notes
1877
1756
  };
@@ -1887,9 +1766,7 @@ var AppointmentService = class extends BaseService {
1887
1766
  */
1888
1767
  async getUpcomingPatientAppointments(patientId, options) {
1889
1768
  try {
1890
- console.log(
1891
- `[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`
1892
- );
1769
+ console.log(`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`);
1893
1770
  const effectiveStartDate = (options == null ? void 0 : options.startDate) || /* @__PURE__ */ new Date();
1894
1771
  const upcomingStatuses = [
1895
1772
  "pending" /* PENDING */,
@@ -1901,21 +1778,9 @@ var AppointmentService = class extends BaseService {
1901
1778
  const constraints = [];
1902
1779
  constraints.push((0, import_firestore2.where)("patientId", "==", patientId));
1903
1780
  constraints.push((0, import_firestore2.where)("status", "in", upcomingStatuses));
1904
- constraints.push(
1905
- (0, import_firestore2.where)(
1906
- "appointmentStartTime",
1907
- ">=",
1908
- import_firestore2.Timestamp.fromDate(effectiveStartDate)
1909
- )
1910
- );
1781
+ constraints.push((0, import_firestore2.where)("appointmentStartTime", ">=", import_firestore2.Timestamp.fromDate(effectiveStartDate)));
1911
1782
  if (options == null ? void 0 : options.endDate) {
1912
- constraints.push(
1913
- (0, import_firestore2.where)(
1914
- "appointmentStartTime",
1915
- "<=",
1916
- import_firestore2.Timestamp.fromDate(options.endDate)
1917
- )
1918
- );
1783
+ constraints.push((0, import_firestore2.where)("appointmentStartTime", "<=", import_firestore2.Timestamp.fromDate(options.endDate)));
1919
1784
  }
1920
1785
  constraints.push((0, import_firestore2.orderBy)("appointmentStartTime", "asc"));
1921
1786
  if (options == null ? void 0 : options.limit) {
@@ -1924,14 +1789,9 @@ var AppointmentService = class extends BaseService {
1924
1789
  if (options == null ? void 0 : options.startAfter) {
1925
1790
  constraints.push((0, import_firestore2.startAfter)(options.startAfter));
1926
1791
  }
1927
- const q = (0, import_firestore2.query)(
1928
- (0, import_firestore2.collection)(this.db, APPOINTMENTS_COLLECTION),
1929
- ...constraints
1930
- );
1792
+ const q = (0, import_firestore2.query)((0, import_firestore2.collection)(this.db, APPOINTMENTS_COLLECTION), ...constraints);
1931
1793
  const querySnapshot = await (0, import_firestore2.getDocs)(q);
1932
- const appointments = querySnapshot.docs.map(
1933
- (doc38) => doc38.data()
1934
- );
1794
+ const appointments = querySnapshot.docs.map((doc38) => doc38.data());
1935
1795
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1936
1796
  console.log(
1937
1797
  `[APPOINTMENT_SERVICE] Found ${appointments.length} upcoming appointments for patient ${patientId}`
@@ -1956,9 +1816,7 @@ var AppointmentService = class extends BaseService {
1956
1816
  */
1957
1817
  async getPastPatientAppointments(patientId, options) {
1958
1818
  try {
1959
- console.log(
1960
- `[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`
1961
- );
1819
+ console.log(`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`);
1962
1820
  const effectiveEndDate = (options == null ? void 0 : options.endDate) || /* @__PURE__ */ new Date();
1963
1821
  const pastStatuses = ["completed" /* COMPLETED */];
1964
1822
  if (options == null ? void 0 : options.showCanceled) {
@@ -1976,20 +1834,10 @@ var AppointmentService = class extends BaseService {
1976
1834
  constraints.push((0, import_firestore2.where)("status", "in", pastStatuses));
1977
1835
  if (options == null ? void 0 : options.startDate) {
1978
1836
  constraints.push(
1979
- (0, import_firestore2.where)(
1980
- "appointmentStartTime",
1981
- ">=",
1982
- import_firestore2.Timestamp.fromDate(options.startDate)
1983
- )
1837
+ (0, import_firestore2.where)("appointmentStartTime", ">=", import_firestore2.Timestamp.fromDate(options.startDate))
1984
1838
  );
1985
1839
  }
1986
- constraints.push(
1987
- (0, import_firestore2.where)(
1988
- "appointmentStartTime",
1989
- "<=",
1990
- import_firestore2.Timestamp.fromDate(effectiveEndDate)
1991
- )
1992
- );
1840
+ constraints.push((0, import_firestore2.where)("appointmentStartTime", "<=", import_firestore2.Timestamp.fromDate(effectiveEndDate)));
1993
1841
  constraints.push((0, import_firestore2.orderBy)("appointmentStartTime", "desc"));
1994
1842
  if (options == null ? void 0 : options.limit) {
1995
1843
  constraints.push((0, import_firestore2.limit)(options.limit));
@@ -1997,14 +1845,9 @@ var AppointmentService = class extends BaseService {
1997
1845
  if (options == null ? void 0 : options.startAfter) {
1998
1846
  constraints.push((0, import_firestore2.startAfter)(options.startAfter));
1999
1847
  }
2000
- const q = (0, import_firestore2.query)(
2001
- (0, import_firestore2.collection)(this.db, APPOINTMENTS_COLLECTION),
2002
- ...constraints
2003
- );
1848
+ const q = (0, import_firestore2.query)((0, import_firestore2.collection)(this.db, APPOINTMENTS_COLLECTION), ...constraints);
2004
1849
  const querySnapshot = await (0, import_firestore2.getDocs)(q);
2005
- const appointments = querySnapshot.docs.map(
2006
- (doc38) => doc38.data()
2007
- );
1850
+ const appointments = querySnapshot.docs.map((doc38) => doc38.data());
2008
1851
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
2009
1852
  console.log(
2010
1853
  `[APPOINTMENT_SERVICE] Found ${appointments.length} past appointments for patient ${patientId}`
@@ -2018,6 +1861,46 @@ var AppointmentService = class extends BaseService {
2018
1861
  throw error;
2019
1862
  }
2020
1863
  }
1864
+ /**
1865
+ * Counts completed appointments for a patient with optional clinic filtering.
1866
+ *
1867
+ * @param patientId ID of the patient.
1868
+ * @param clinicBranchId Optional ID of the clinic branch to either include or exclude.
1869
+ * @param excludeClinic Optional boolean. If true (default), excludes the specified clinic. If false, includes only that clinic.
1870
+ * @returns The count of completed appointments.
1871
+ */
1872
+ async countCompletedAppointments(patientId, clinicBranchId, excludeClinic = true) {
1873
+ try {
1874
+ console.log(
1875
+ `[APPOINTMENT_SERVICE] Counting completed appointments for patient: ${patientId}`,
1876
+ { clinicBranchId, excludeClinic }
1877
+ );
1878
+ const constraints = [
1879
+ (0, import_firestore2.where)("patientId", "==", patientId),
1880
+ (0, import_firestore2.where)("status", "==", "completed" /* COMPLETED */)
1881
+ ];
1882
+ if (clinicBranchId) {
1883
+ if (excludeClinic) {
1884
+ constraints.push((0, import_firestore2.where)("clinicBranchId", "!=", clinicBranchId));
1885
+ } else {
1886
+ constraints.push((0, import_firestore2.where)("clinicBranchId", "==", clinicBranchId));
1887
+ }
1888
+ }
1889
+ const q = (0, import_firestore2.query)((0, import_firestore2.collection)(this.db, APPOINTMENTS_COLLECTION), ...constraints);
1890
+ const snapshot = await (0, import_firestore2.getCountFromServer)(q);
1891
+ const count = snapshot.data().count;
1892
+ console.log(
1893
+ `[APPOINTMENT_SERVICE] Found ${count} completed appointments for patient ${patientId}`
1894
+ );
1895
+ return count;
1896
+ } catch (error) {
1897
+ console.error(
1898
+ `[APPOINTMENT_SERVICE] Error counting completed appointments for patient ${patientId}:`,
1899
+ error
1900
+ );
1901
+ throw error;
1902
+ }
1903
+ }
2021
1904
  };
2022
1905
 
2023
1906
  // src/services/auth/auth.service.ts
@@ -7880,7 +7763,10 @@ var BillingTransactionsService = class extends BaseService {
7880
7763
  "subscription_reactivated" /* SUBSCRIPTION_REACTIVATED */,
7881
7764
  "subscription_deleted" /* SUBSCRIPTION_DELETED */
7882
7765
  ];
7883
- const constraints = [(0, import_firestore23.where)("type", "in", subscriptionTypes), (0, import_firestore23.orderBy)("timestamp", "desc")];
7766
+ const constraints = [
7767
+ (0, import_firestore23.where)("type", "in", subscriptionTypes),
7768
+ (0, import_firestore23.orderBy)("timestamp", "desc")
7769
+ ];
7884
7770
  if (startAfterDoc) {
7885
7771
  constraints.push((0, import_firestore23.startAfter)(startAfterDoc));
7886
7772
  }
@@ -9888,19 +9774,13 @@ var AuthService = class extends BaseService {
9888
9774
  constructor(db, auth, app, userService) {
9889
9775
  super(db, auth, app);
9890
9776
  this.googleProvider = new import_auth7.GoogleAuthProvider();
9891
- this.facebookProvider = new import_auth7.FacebookAuthProvider();
9892
- this.appleProvider = new import_auth7.OAuthProvider("apple.com");
9893
9777
  this.userService = userService || new UserService(db, auth, app);
9894
9778
  }
9895
9779
  /**
9896
9780
  * Registruje novog korisnika sa email-om i lozinkom
9897
9781
  */
9898
9782
  async signUp(email, password, initialRole = "patient" /* PATIENT */, options) {
9899
- const { user: firebaseUser } = await (0, import_auth7.createUserWithEmailAndPassword)(
9900
- this.auth,
9901
- email,
9902
- password
9903
- );
9783
+ const { user: firebaseUser } = await (0, import_auth7.createUserWithEmailAndPassword)(this.auth, email, password);
9904
9784
  return this.userService.createUser(firebaseUser, [initialRole], options);
9905
9785
  }
9906
9786
  /**
@@ -9919,20 +9799,13 @@ var AuthService = class extends BaseService {
9919
9799
  await clinicAdminSignupSchema.parseAsync(data);
9920
9800
  console.log("[AUTH] Clinic admin signup data validation passed");
9921
9801
  } catch (validationError) {
9922
- console.error(
9923
- "[AUTH] Validation error in signUpClinicAdmin:",
9924
- validationError
9925
- );
9802
+ console.error("[AUTH] Validation error in signUpClinicAdmin:", validationError);
9926
9803
  throw validationError;
9927
9804
  }
9928
9805
  console.log("[AUTH] Creating Firebase user");
9929
9806
  let firebaseUser;
9930
9807
  try {
9931
- const result = await (0, import_auth7.createUserWithEmailAndPassword)(
9932
- this.auth,
9933
- data.email,
9934
- data.password
9935
- );
9808
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(this.auth, data.email, data.password);
9936
9809
  firebaseUser = result.user;
9937
9810
  console.log("[AUTH] Firebase user created successfully", {
9938
9811
  uid: firebaseUser.uid
@@ -9944,13 +9817,9 @@ var AuthService = class extends BaseService {
9944
9817
  console.log("[AUTH] Creating user with CLINIC_ADMIN role");
9945
9818
  let user;
9946
9819
  try {
9947
- user = await this.userService.createUser(
9948
- firebaseUser,
9949
- ["clinic_admin" /* CLINIC_ADMIN */],
9950
- {
9951
- skipProfileCreation: true
9952
- }
9953
- );
9820
+ user = await this.userService.createUser(firebaseUser, ["clinic_admin" /* CLINIC_ADMIN */], {
9821
+ skipProfileCreation: true
9822
+ });
9954
9823
  console.log("[AUTH] User with CLINIC_ADMIN role created successfully", {
9955
9824
  userId: user.uid
9956
9825
  });
@@ -9967,11 +9836,7 @@ var AuthService = class extends BaseService {
9967
9836
  };
9968
9837
  console.log("[AUTH] Contact person object created");
9969
9838
  console.log("[AUTH] Initializing clinic services");
9970
- const clinicAdminService = new ClinicAdminService(
9971
- this.db,
9972
- this.auth,
9973
- this.app
9974
- );
9839
+ const clinicAdminService = new ClinicAdminService(this.db, this.auth, this.app);
9975
9840
  const clinicGroupService = new ClinicGroupService(
9976
9841
  this.db,
9977
9842
  this.auth,
@@ -9988,18 +9853,14 @@ var AuthService = class extends BaseService {
9988
9853
  mediaService
9989
9854
  );
9990
9855
  clinicAdminService.setServices(clinicGroupService, clinicService);
9991
- console.log(
9992
- "[AUTH] Services initialized and circular dependencies resolved"
9993
- );
9856
+ console.log("[AUTH] Services initialized and circular dependencies resolved");
9994
9857
  let clinicGroup = null;
9995
9858
  let adminProfile = null;
9996
9859
  if (data.isCreatingNewGroup) {
9997
9860
  console.log("[AUTH] Creating new clinic group flow");
9998
9861
  if (!data.clinicGroupData) {
9999
9862
  console.error("[AUTH] Clinic group data is missing");
10000
- throw new Error(
10001
- "Clinic group data is required when creating a new group"
10002
- );
9863
+ throw new Error("Clinic group data is required when creating a new group");
10003
9864
  }
10004
9865
  console.log("[AUTH] Creating clinic admin first (without group)");
10005
9866
  const createClinicAdminData = {
@@ -10012,17 +9873,12 @@ var AuthService = class extends BaseService {
10012
9873
  // No clinicGroupId yet
10013
9874
  };
10014
9875
  try {
10015
- adminProfile = await clinicAdminService.createClinicAdmin(
10016
- createClinicAdminData
10017
- );
9876
+ adminProfile = await clinicAdminService.createClinicAdmin(createClinicAdminData);
10018
9877
  console.log("[AUTH] Clinic admin created successfully", {
10019
9878
  adminId: adminProfile.id
10020
9879
  });
10021
9880
  } catch (adminCreationError) {
10022
- console.error(
10023
- "[AUTH] Clinic admin creation failed:",
10024
- adminCreationError
10025
- );
9881
+ console.error("[AUTH] Clinic admin creation failed:", adminCreationError);
10026
9882
  throw adminCreationError;
10027
9883
  }
10028
9884
  try {
@@ -10030,14 +9886,9 @@ var AuthService = class extends BaseService {
10030
9886
  user = await this.userService.updateUser(firebaseUser.uid, {
10031
9887
  adminProfile: adminProfile.id
10032
9888
  });
10033
- console.log(
10034
- "[AUTH] User updated with admin profile reference successfully"
10035
- );
9889
+ console.log("[AUTH] User updated with admin profile reference successfully");
10036
9890
  } catch (userUpdateError) {
10037
- console.error(
10038
- "[AUTH] Failed to update user with admin profile:",
10039
- userUpdateError
10040
- );
9891
+ console.error("[AUTH] Failed to update user with admin profile:", userUpdateError);
10041
9892
  throw userUpdateError;
10042
9893
  }
10043
9894
  const createClinicGroupData = {
@@ -10075,23 +9926,16 @@ var AuthService = class extends BaseService {
10075
9926
  clinicGroupId: clinicGroup.id
10076
9927
  });
10077
9928
  console.log("[AUTH] Admin updated with clinic group ID successfully");
10078
- adminProfile = await clinicAdminService.getClinicAdmin(
10079
- adminProfile.id
10080
- );
9929
+ adminProfile = await clinicAdminService.getClinicAdmin(adminProfile.id);
10081
9930
  } catch (groupCreationError) {
10082
- console.error(
10083
- "[AUTH] Clinic group creation failed:",
10084
- groupCreationError
10085
- );
9931
+ console.error("[AUTH] Clinic group creation failed:", groupCreationError);
10086
9932
  throw groupCreationError;
10087
9933
  }
10088
9934
  } else {
10089
9935
  console.log("[AUTH] Joining existing clinic group flow");
10090
9936
  if (!data.inviteToken) {
10091
9937
  console.error("[AUTH] Invite token is missing");
10092
- throw new Error(
10093
- "Invite token is required when joining an existing group"
10094
- );
9938
+ throw new Error("Invite token is required when joining an existing group");
10095
9939
  }
10096
9940
  console.log("[AUTH] Invite token provided", {
10097
9941
  token: data.inviteToken
@@ -10102,11 +9946,7 @@ var AuthService = class extends BaseService {
10102
9946
  const querySnapshot = await (0, import_firestore29.getDocs)(q);
10103
9947
  let foundGroup = null;
10104
9948
  let foundToken = null;
10105
- console.log(
10106
- "[AUTH] Found",
10107
- querySnapshot.size,
10108
- "clinic groups to check"
10109
- );
9949
+ console.log("[AUTH] Found", querySnapshot.size, "clinic groups to check");
10110
9950
  for (const docSnapshot of querySnapshot.docs) {
10111
9951
  const group = docSnapshot.data();
10112
9952
  console.log("[AUTH] Checking group", {
@@ -10152,17 +9992,12 @@ var AuthService = class extends BaseService {
10152
9992
  isActive: true
10153
9993
  };
10154
9994
  try {
10155
- adminProfile = await clinicAdminService.createClinicAdmin(
10156
- createClinicAdminData
10157
- );
9995
+ adminProfile = await clinicAdminService.createClinicAdmin(createClinicAdminData);
10158
9996
  console.log("[AUTH] Clinic admin created successfully", {
10159
9997
  adminId: adminProfile.id
10160
9998
  });
10161
9999
  } catch (adminCreationError) {
10162
- console.error(
10163
- "[AUTH] Clinic admin creation failed:",
10164
- adminCreationError
10165
- );
10000
+ console.error("[AUTH] Clinic admin creation failed:", adminCreationError);
10166
10001
  throw adminCreationError;
10167
10002
  }
10168
10003
  try {
@@ -10183,9 +10018,7 @@ var AuthService = class extends BaseService {
10183
10018
  clinicAdminId: (adminProfile == null ? void 0 : adminProfile.id) || "unknown"
10184
10019
  });
10185
10020
  if (!clinicGroup || !adminProfile) {
10186
- throw new Error(
10187
- "Failed to create or retrieve clinic group or admin profile"
10188
- );
10021
+ throw new Error("Failed to create or retrieve clinic group or admin profile");
10189
10022
  }
10190
10023
  return {
10191
10024
  user,
@@ -10213,11 +10046,7 @@ var AuthService = class extends BaseService {
10213
10046
  * Prijavljuje korisnika sa email-om i lozinkom
10214
10047
  */
10215
10048
  async signIn(email, password) {
10216
- const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
10217
- this.auth,
10218
- email,
10219
- password
10220
- );
10049
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(this.auth, email, password);
10221
10050
  return this.userService.getOrCreateUser(firebaseUser);
10222
10051
  }
10223
10052
  /**
@@ -10231,11 +10060,7 @@ var AuthService = class extends BaseService {
10231
10060
  async signInClinicAdmin(email, password) {
10232
10061
  var _a;
10233
10062
  try {
10234
- const clinicAdminService = new ClinicAdminService(
10235
- this.db,
10236
- this.auth,
10237
- this.app
10238
- );
10063
+ const clinicAdminService = new ClinicAdminService(this.db, this.auth, this.app);
10239
10064
  const clinicGroupService = new ClinicGroupService(
10240
10065
  this.db,
10241
10066
  this.auth,
@@ -10252,11 +10077,7 @@ var AuthService = class extends BaseService {
10252
10077
  mediaService
10253
10078
  );
10254
10079
  clinicAdminService.setServices(clinicGroupService, clinicService);
10255
- const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
10256
- this.auth,
10257
- email,
10258
- password
10259
- );
10080
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(this.auth, email, password);
10260
10081
  const user = await this.userService.getOrCreateUser(firebaseUser);
10261
10082
  if (!((_a = user.roles) == null ? void 0 : _a.includes("clinic_admin" /* CLINIC_ADMIN */))) {
10262
10083
  console.error("[AUTH] User is not a clinic admin:", user.uid);
@@ -10266,21 +10087,14 @@ var AuthService = class extends BaseService {
10266
10087
  console.error("[AUTH] User has no admin profile:", user.uid);
10267
10088
  throw AUTH_ERRORS.NOT_FOUND;
10268
10089
  }
10269
- const adminProfile = await clinicAdminService.getClinicAdmin(
10270
- user.adminProfile
10271
- );
10090
+ const adminProfile = await clinicAdminService.getClinicAdmin(user.adminProfile);
10272
10091
  if (!adminProfile) {
10273
10092
  console.error("[AUTH] Admin profile not found:", user.adminProfile);
10274
10093
  throw AUTH_ERRORS.NOT_FOUND;
10275
10094
  }
10276
- const clinicGroup = await clinicGroupService.getClinicGroup(
10277
- adminProfile.clinicGroupId
10278
- );
10095
+ const clinicGroup = await clinicGroupService.getClinicGroup(adminProfile.clinicGroupId);
10279
10096
  if (!clinicGroup) {
10280
- console.error(
10281
- "[AUTH] Clinic group not found:",
10282
- adminProfile.clinicGroupId
10283
- );
10097
+ console.error("[AUTH] Clinic group not found:", adminProfile.clinicGroupId);
10284
10098
  throw AUTH_ERRORS.NOT_FOUND;
10285
10099
  }
10286
10100
  return {
@@ -10293,39 +10107,6 @@ var AuthService = class extends BaseService {
10293
10107
  throw error;
10294
10108
  }
10295
10109
  }
10296
- /**
10297
- * Prijavljuje korisnika sa Facebook-om
10298
- */
10299
- async signInWithFacebook() {
10300
- const provider = new import_auth7.FacebookAuthProvider();
10301
- const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
10302
- return this.userService.getOrCreateUser(firebaseUser);
10303
- }
10304
- /**
10305
- * Prijavljuje korisnika sa Google nalogom
10306
- */
10307
- async signInWithGoogle(initialRole = "patient" /* PATIENT */, options) {
10308
- const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(
10309
- this.auth,
10310
- this.googleProvider
10311
- );
10312
- const existingUser = await this.userService.getUserByEmail(
10313
- firebaseUser.email
10314
- );
10315
- if (existingUser) {
10316
- await this.userService.updateUserLoginTimestamp(existingUser.uid);
10317
- return existingUser;
10318
- }
10319
- return this.userService.createUser(firebaseUser, [initialRole], options);
10320
- }
10321
- /**
10322
- * Prijavljuje korisnika sa Apple-om
10323
- */
10324
- async signInWithApple() {
10325
- const provider = new import_auth7.OAuthProvider("apple.com");
10326
- const { user: firebaseUser } = await (0, import_auth7.signInWithPopup)(this.auth, provider);
10327
- return this.userService.getOrCreateUser(firebaseUser);
10328
- }
10329
10110
  /**
10330
10111
  * Prijavljuje korisnika anonimno
10331
10112
  */
@@ -10362,18 +10143,11 @@ var AuthService = class extends BaseService {
10362
10143
  throw AUTH_ERRORS.NOT_AUTHENTICATED;
10363
10144
  }
10364
10145
  if (!currentUser.isAnonymous) {
10365
- throw new AuthError(
10366
- "User is not anonymous",
10367
- "AUTH/NOT_ANONYMOUS_USER",
10368
- 400
10369
- );
10146
+ throw new AuthError("User is not anonymous", "AUTH/NOT_ANONYMOUS_USER", 400);
10370
10147
  }
10371
10148
  const credential = import_auth7.EmailAuthProvider.credential(email, password);
10372
10149
  await (0, import_auth7.linkWithCredential)(currentUser, credential);
10373
- return await this.userService.upgradeAnonymousUser(
10374
- currentUser.uid,
10375
- email
10376
- );
10150
+ return await this.userService.upgradeAnonymousUser(currentUser.uid, email);
10377
10151
  } catch (error) {
10378
10152
  if (error instanceof import_zod23.z.ZodError) {
10379
10153
  throw AUTH_ERRORS.VALIDATION_ERROR;
@@ -10385,109 +10159,6 @@ var AuthService = class extends BaseService {
10385
10159
  throw error;
10386
10160
  }
10387
10161
  }
10388
- /**
10389
- * Upgrades an anonymous user to a regular user by signing in with a Google account.
10390
- *
10391
- * @throws {AuthError} If the user is not anonymous.
10392
- * @throws {AuthError} If the user is not authenticated.
10393
- * @throws {AuthError} If the popup window is closed by the user.
10394
- * @throws {FirebaseError} If any other Firebase error occurs.
10395
- *
10396
- * @returns {Promise<User>} The upgraded user.
10397
- */
10398
- async upgradeAnonymousUserWithGoogle() {
10399
- try {
10400
- const currentUser = this.auth.currentUser;
10401
- if (!currentUser) {
10402
- throw AUTH_ERRORS.NOT_AUTHENTICATED;
10403
- }
10404
- if (!currentUser.isAnonymous) {
10405
- throw new AuthError(
10406
- "User is not anonymous",
10407
- "AUTH/NOT_ANONYMOUS_USER",
10408
- 400
10409
- );
10410
- }
10411
- const userCredential = await (0, import_auth7.signInWithPopup)(
10412
- this.auth,
10413
- this.googleProvider
10414
- );
10415
- if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
10416
- return await this.userService.upgradeAnonymousUser(
10417
- currentUser.uid,
10418
- userCredential.user.email
10419
- );
10420
- } catch (error) {
10421
- const firebaseError = error;
10422
- if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
10423
- throw AUTH_ERRORS.POPUP_CLOSED;
10424
- }
10425
- throw error;
10426
- }
10427
- }
10428
- async upgradeAnonymousUserWithFacebook() {
10429
- try {
10430
- const currentUser = this.auth.currentUser;
10431
- if (!currentUser) {
10432
- throw AUTH_ERRORS.NOT_AUTHENTICATED;
10433
- }
10434
- if (!currentUser.isAnonymous) {
10435
- throw new AuthError(
10436
- "User is not anonymous",
10437
- "AUTH/NOT_ANONYMOUS_USER",
10438
- 400
10439
- );
10440
- }
10441
- this.facebookProvider.addScope("email");
10442
- const userCredential = await (0, import_auth7.signInWithPopup)(
10443
- this.auth,
10444
- this.facebookProvider
10445
- );
10446
- if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
10447
- return await this.userService.upgradeAnonymousUser(
10448
- currentUser.uid,
10449
- userCredential.user.email
10450
- );
10451
- } catch (error) {
10452
- const firebaseError = error;
10453
- if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
10454
- throw AUTH_ERRORS.POPUP_CLOSED;
10455
- }
10456
- throw error;
10457
- }
10458
- }
10459
- async upgradeAnonymousUserWithApple() {
10460
- try {
10461
- const currentUser = this.auth.currentUser;
10462
- if (!currentUser) {
10463
- throw AUTH_ERRORS.NOT_AUTHENTICATED;
10464
- }
10465
- if (!currentUser.isAnonymous) {
10466
- throw new AuthError(
10467
- "User is not anonymous",
10468
- "AUTH/NOT_ANONYMOUS_USER",
10469
- 400
10470
- );
10471
- }
10472
- this.appleProvider.addScope("email");
10473
- this.appleProvider.addScope("name");
10474
- const userCredential = await (0, import_auth7.signInWithPopup)(
10475
- this.auth,
10476
- this.appleProvider
10477
- );
10478
- if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
10479
- return await this.userService.upgradeAnonymousUser(
10480
- currentUser.uid,
10481
- userCredential.user.email
10482
- );
10483
- } catch (error) {
10484
- const firebaseError = error;
10485
- if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
10486
- throw AUTH_ERRORS.POPUP_CLOSED;
10487
- }
10488
- throw error;
10489
- }
10490
- }
10491
10162
  /**
10492
10163
  * Šalje email za resetovanje lozinke korisniku
10493
10164
  * @param email Email adresa korisnika
@@ -10568,11 +10239,7 @@ var AuthService = class extends BaseService {
10568
10239
  await this.validateSignupData(data);
10569
10240
  console.log("[AUTH] Creating Firebase user");
10570
10241
  try {
10571
- const result = await (0, import_auth7.createUserWithEmailAndPassword)(
10572
- this.auth,
10573
- data.email,
10574
- data.password
10575
- );
10242
+ const result = await (0, import_auth7.createUserWithEmailAndPassword)(this.auth, data.email, data.password);
10576
10243
  firebaseUser = result.user;
10577
10244
  console.log("[AUTH] Firebase user created successfully", {
10578
10245
  uid: firebaseUser.uid
@@ -10582,64 +10249,43 @@ var AuthService = class extends BaseService {
10582
10249
  throw handleFirebaseError(firebaseError);
10583
10250
  }
10584
10251
  console.log("[AUTH] Starting Firestore transaction");
10585
- const transactionResult = await (0, import_firestore29.runTransaction)(
10586
- this.db,
10587
- async (transaction) => {
10588
- console.log(
10589
- "[AUTH] Transaction started - creating user and practitioner"
10590
- );
10591
- const practitionerService = new PractitionerService(
10592
- this.db,
10593
- this.auth,
10594
- this.app
10595
- );
10596
- console.log("[AUTH] Creating user document");
10597
- const user = await this.userService.createUser(
10598
- firebaseUser,
10599
- ["practitioner" /* PRACTITIONER */],
10600
- { skipProfileCreation: true }
10252
+ const transactionResult = await (0, import_firestore29.runTransaction)(this.db, async (transaction) => {
10253
+ console.log("[AUTH] Transaction started - creating user and practitioner");
10254
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
10255
+ console.log("[AUTH] Creating user document");
10256
+ const user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
10257
+ skipProfileCreation: true
10258
+ });
10259
+ let practitioner;
10260
+ if (data.token) {
10261
+ console.log("[AUTH] Claiming existing practitioner profile with token");
10262
+ const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
10263
+ data.token,
10264
+ firebaseUser.uid
10601
10265
  );
10602
- let practitioner;
10603
- if (data.token) {
10604
- console.log(
10605
- "[AUTH] Claiming existing practitioner profile with token"
10606
- );
10607
- const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
10608
- data.token,
10609
- firebaseUser.uid
10610
- );
10611
- if (!claimedPractitioner) {
10612
- throw new Error("Invalid or expired invitation token");
10613
- }
10614
- practitioner = claimedPractitioner;
10615
- } else {
10616
- console.log("[AUTH] Creating new practitioner profile");
10617
- const practitionerData = buildPractitionerData(
10618
- data,
10619
- firebaseUser.uid
10620
- );
10621
- practitioner = await practitionerService.createPractitioner(
10622
- practitionerData
10623
- );
10266
+ if (!claimedPractitioner) {
10267
+ throw new Error("Invalid or expired invitation token");
10624
10268
  }
10625
- console.log("[AUTH] Linking practitioner to user");
10626
- await this.userService.updateUser(firebaseUser.uid, {
10627
- practitionerProfile: practitioner.id
10628
- });
10629
- console.log("[AUTH] Transaction operations completed successfully");
10630
- return { user, practitioner };
10269
+ practitioner = claimedPractitioner;
10270
+ } else {
10271
+ console.log("[AUTH] Creating new practitioner profile");
10272
+ const practitionerData = buildPractitionerData(data, firebaseUser.uid);
10273
+ practitioner = await practitionerService.createPractitioner(practitionerData);
10631
10274
  }
10632
- );
10275
+ console.log("[AUTH] Linking practitioner to user");
10276
+ await this.userService.updateUser(firebaseUser.uid, {
10277
+ practitionerProfile: practitioner.id
10278
+ });
10279
+ console.log("[AUTH] Transaction operations completed successfully");
10280
+ return { user, practitioner };
10281
+ });
10633
10282
  console.log("[AUTH] Atomic practitioner signup completed successfully", {
10634
10283
  userId: transactionResult.user.uid,
10635
10284
  practitionerId: transactionResult.practitioner.id
10636
10285
  });
10637
10286
  return transactionResult;
10638
10287
  } catch (error) {
10639
- console.error(
10640
- "[AUTH] Atomic signup failed, initiating cleanup...",
10641
- error
10642
- );
10288
+ console.error("[AUTH] Atomic signup failed, initiating cleanup...", error);
10643
10289
  if (firebaseUser) {
10644
10290
  await cleanupFirebaseUser(firebaseUser);
10645
10291
  }
@@ -10662,14 +10308,8 @@ var AuthService = class extends BaseService {
10662
10308
  }
10663
10309
  console.log("[AUTH] Email availability confirmed");
10664
10310
  if (data.token) {
10665
- const practitionerService = new PractitionerService(
10666
- this.db,
10667
- this.auth,
10668
- this.app
10669
- );
10670
- const isValidToken = await practitionerService.validateToken(
10671
- data.token
10672
- );
10311
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
10312
+ const isValidToken = await practitionerService.validateToken(data.token);
10673
10313
  if (!isValidToken) {
10674
10314
  console.log("[AUTH] Invalid token provided:", data.token);
10675
10315
  throw new Error("Invalid or expired invitation token");
@@ -10700,16 +10340,8 @@ var AuthService = class extends BaseService {
10700
10340
  console.log("[AUTH] Starting practitioner signin process", {
10701
10341
  email
10702
10342
  });
10703
- const practitionerService = new PractitionerService(
10704
- this.db,
10705
- this.auth,
10706
- this.app
10707
- );
10708
- const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(
10709
- this.auth,
10710
- email,
10711
- password
10712
- );
10343
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
10344
+ const { user: firebaseUser } = await (0, import_auth7.signInWithEmailAndPassword)(this.auth, email, password);
10713
10345
  const user = await this.userService.getOrCreateUser(firebaseUser);
10714
10346
  console.log("[AUTH] User retrieved", { uid: user.uid });
10715
10347
  if (!((_a = user.roles) == null ? void 0 : _a.includes("practitioner" /* PRACTITIONER */))) {
@@ -10720,14 +10352,9 @@ var AuthService = class extends BaseService {
10720
10352
  console.error("[AUTH] User has no practitioner profile:", user.uid);
10721
10353
  throw AUTH_ERRORS.NOT_FOUND;
10722
10354
  }
10723
- const practitioner = await practitionerService.getPractitioner(
10724
- user.practitionerProfile
10725
- );
10355
+ const practitioner = await practitionerService.getPractitioner(user.practitionerProfile);
10726
10356
  if (!practitioner) {
10727
- console.error(
10728
- "[AUTH] Practitioner profile not found:",
10729
- user.practitionerProfile
10730
- );
10357
+ console.error("[AUTH] Practitioner profile not found:", user.practitionerProfile);
10731
10358
  throw AUTH_ERRORS.NOT_FOUND;
10732
10359
  }
10733
10360
  console.log("[AUTH] Practitioner signin completed successfully", {
@@ -10743,6 +10370,64 @@ var AuthService = class extends BaseService {
10743
10370
  throw error;
10744
10371
  }
10745
10372
  }
10373
+ /**
10374
+ * Signs in a user with a Google ID token from a mobile client.
10375
+ * If the user does not exist, a new user is created.
10376
+ * @param idToken - The Google ID token obtained from the mobile app.
10377
+ * @param initialRole - The role to assign to the user if they are being created.
10378
+ * @returns The signed-in or newly created user.
10379
+ */
10380
+ async signInWithGoogleIdToken(idToken, initialRole = "patient" /* PATIENT */) {
10381
+ try {
10382
+ console.log("[AUTH] Signing in with Google ID Token");
10383
+ const credential = import_auth7.GoogleAuthProvider.credential(idToken);
10384
+ const { user: firebaseUser } = await (0, import_auth7.signInWithCredential)(this.auth, credential);
10385
+ console.log("[AUTH] Firebase user signed in:", firebaseUser.uid);
10386
+ const existingUser = await this.userService.getUserById(firebaseUser.uid);
10387
+ if (existingUser) {
10388
+ console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
10389
+ return existingUser;
10390
+ }
10391
+ console.log("[AUTH] No existing user found, creating new profile for:", firebaseUser.uid);
10392
+ return this.userService.createUser(firebaseUser, [initialRole]);
10393
+ } catch (error) {
10394
+ console.error("[AUTH] Error in signInWithGoogleIdToken:", error);
10395
+ throw handleFirebaseError(error);
10396
+ }
10397
+ }
10398
+ /**
10399
+ * Links a Google account to the currently signed-in user using an ID token.
10400
+ * This is used to upgrade an anonymous user or to allow an existing user
10401
+ * to sign in with Google in the future.
10402
+ * @param idToken - The Google ID token obtained from the mobile app.
10403
+ * @returns The updated user profile.
10404
+ */
10405
+ async linkGoogleAccount(idToken) {
10406
+ try {
10407
+ console.log("[AUTH] Linking Google account with ID Token");
10408
+ const currentUser = this.auth.currentUser;
10409
+ if (!currentUser) {
10410
+ throw AUTH_ERRORS.NOT_AUTHENTICATED;
10411
+ }
10412
+ const wasAnonymous = currentUser.isAnonymous;
10413
+ console.log(`[AUTH] Current user is ${wasAnonymous ? "anonymous" : "not anonymous"}`);
10414
+ const credential = import_auth7.GoogleAuthProvider.credential(idToken);
10415
+ const userCredential = await (0, import_auth7.linkWithCredential)(currentUser, credential);
10416
+ const linkedFirebaseUser = userCredential.user;
10417
+ console.log("[AUTH] Google account linked successfully to user:", linkedFirebaseUser.uid);
10418
+ if (wasAnonymous) {
10419
+ console.log("[AUTH] Upgrading anonymous user profile");
10420
+ return await this.userService.upgradeAnonymousUser(
10421
+ linkedFirebaseUser.uid,
10422
+ linkedFirebaseUser.email
10423
+ );
10424
+ }
10425
+ return await this.userService.getUserById(linkedFirebaseUser.uid);
10426
+ } catch (error) {
10427
+ console.error("[AUTH] Error in linkGoogleAccount:", error);
10428
+ throw handleFirebaseError(error);
10429
+ }
10430
+ }
10746
10431
  };
10747
10432
 
10748
10433
  // src/services/calendar/calendar.v2.service.ts