import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:uuid/uuid.dart'; import '../models/time_registration.dart'; class TimeService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; final Uuid _uuid = const Uuid(); // Start ny timeregistrering (stempling) Future startTimer({ required String userId, required String organizationId, RegistrationType type = RegistrationType.ordinary, String? projectId, String? customerId, String? comment, }) async { try { final registration = TimeRegistration( id: _uuid.v4(), userId: userId, organizationId: organizationId, startTime: DateTime.now(), endTime: null, // Ikke avsluttet ennå duration: 0, type: type, projectId: projectId, customerId: customerId, comment: comment, breaks: [], createdAt: DateTime.now(), updatedAt: DateTime.now(), createdBy: userId, isManual: false, ); await _firestore .collection('time_registrations') .doc(registration.id) .set(registration.toFirestore()); return registration.id; } catch (e) { throw Exception('Kunne ikke starte timer: $e'); } } // Stopp pågående timeregistrering Future stopTimer(String registrationId, String userId) async { try { final doc = await _firestore .collection('time_registrations') .doc(registrationId) .get(); if (!doc.exists) { throw Exception('Timeregistrering ikke funnet'); } final registration = TimeRegistration.fromFirestore(doc); final endTime = DateTime.now(); final duration = endTime.difference(registration.startTime).inMinutes; await _firestore .collection('time_registrations') .doc(registrationId) .update({ 'endTime': Timestamp.fromDate(endTime), 'duration': duration, 'updatedAt': Timestamp.fromDate(DateTime.now()), 'lastModifiedBy': userId, }); } catch (e) { throw Exception('Kunne ikke stoppe timer: $e'); } } // Opprett manuell timeregistrering Future createManualEntry({ required String userId, required String organizationId, required DateTime startTime, required DateTime endTime, RegistrationType type = RegistrationType.ordinary, List breaks = const [], String? projectId, String? customerId, String? comment, }) async { try { final duration = endTime.difference(startTime).inMinutes; final registration = TimeRegistration( id: _uuid.v4(), userId: userId, organizationId: organizationId, startTime: startTime, endTime: endTime, duration: duration, type: type, projectId: projectId, customerId: customerId, comment: comment, breaks: breaks, createdAt: DateTime.now(), updatedAt: DateTime.now(), createdBy: userId, isManual: true, ); await _firestore .collection('time_registrations') .doc(registration.id) .set(registration.toFirestore()); return registration.id; } catch (e) { throw Exception('Kunne ikke opprette timeregistrering: $e'); } } // Oppdater eksisterende timeregistrering Future updateRegistration({ required String registrationId, required String userId, DateTime? startTime, DateTime? endTime, RegistrationType? type, List? breaks, String? projectId, String? customerId, String? comment, }) async { try { final doc = await _firestore .collection('time_registrations') .doc(registrationId) .get(); if (!doc.exists) { throw Exception('Timeregistrering ikke funnet'); } final registration = TimeRegistration.fromFirestore(doc); final Map updates = { 'updatedAt': Timestamp.fromDate(DateTime.now()), 'lastModifiedBy': userId, }; if (startTime != null) { updates['startTime'] = Timestamp.fromDate(startTime); } if (endTime != null) { updates['endTime'] = Timestamp.fromDate(endTime); } if (type != null) { updates['type'] = type.name; } if (breaks != null) { updates['breaks'] = breaks.map((b) => b.toMap()).toList(); } if (projectId != null) { updates['projectId'] = projectId; } if (customerId != null) { updates['customerId'] = customerId; } if (comment != null) { updates['comment'] = comment; } // Beregn ny varighet hvis start eller slutt er endret final newStartTime = startTime ?? registration.startTime; final newEndTime = endTime ?? registration.endTime; if (newEndTime != null) { updates['duration'] = newEndTime.difference(newStartTime).inMinutes; } await _firestore .collection('time_registrations') .doc(registrationId) .update(updates); } catch (e) { throw Exception('Kunne ikke oppdatere timeregistrering: $e'); } } // Slett timeregistrering Future deleteRegistration(String registrationId) async { try { await _firestore .collection('time_registrations') .doc(registrationId) .delete(); } catch (e) { throw Exception('Kunne ikke slette timeregistrering: $e'); } } // Hent alle timeregistreringer for bruker i en periode Future> getRegistrations({ required String userId, DateTime? startDate, DateTime? endDate, }) async { try { Query query = _firestore .collection('time_registrations') .where('userId', isEqualTo: userId); if (startDate != null) { query = query.where('startTime', isGreaterThanOrEqualTo: Timestamp.fromDate(startDate)); } if (endDate != null) { query = query.where('startTime', isLessThanOrEqualTo: Timestamp.fromDate(endDate)); } final snapshot = await query.orderBy('startTime', descending: true).get(); return snapshot.docs .map((doc) => TimeRegistration.fromFirestore(doc)) .toList(); } catch (e) { throw Exception('Kunne ikke hente timeregistreringer: $e'); } } // Hent timeregistreringer for en spesifikk dag Future> getRegistrationsByDay({ required String userId, required DateTime date, }) async { final startOfDay = DateTime(date.year, date.month, date.day); final endOfDay = DateTime(date.year, date.month, date.day, 23, 59, 59); return getRegistrations( userId: userId, startDate: startOfDay, endDate: endOfDay, ); } // Hent pågående timeregistrering Future getActiveRegistration(String userId) async { try { final snapshot = await _firestore .collection('time_registrations') .where('userId', isEqualTo: userId) .where('endTime', isNull: true) .limit(1) .get(); if (snapshot.docs.isNotEmpty) { return TimeRegistration.fromFirestore(snapshot.docs.first); } return null; } catch (e) { throw Exception('Kunne ikke hente aktiv timeregistrering: $e'); } } // Stream av timeregistreringer for bruker Stream> registrationsStream({ required String userId, DateTime? startDate, DateTime? endDate, }) { Query query = _firestore .collection('time_registrations') .where('userId', isEqualTo: userId); if (startDate != null) { query = query.where('startTime', isGreaterThanOrEqualTo: Timestamp.fromDate(startDate)); } if (endDate != null) { query = query.where('startTime', isLessThanOrEqualTo: Timestamp.fromDate(endDate)); } return query.orderBy('startTime', descending: true).snapshots().map( (snapshot) => snapshot.docs .map((doc) => TimeRegistration.fromFirestore(doc)) .toList(), ); } // Beregn total arbeidstid for en periode Future> calculateTotalHours({ required String userId, required DateTime startDate, required DateTime endDate, }) async { final registrations = await getRegistrations( userId: userId, startDate: startDate, endDate: endDate, ); int totalMinutes = 0; int ordinaryMinutes = 0; int overtimeMinutes = 0; for (final reg in registrations) { if (reg.endTime != null) { totalMinutes += reg.netWorkMinutes; if (reg.type == RegistrationType.ordinary) { ordinaryMinutes += reg.netWorkMinutes; } else if (reg.type == RegistrationType.overtime) { overtimeMinutes += reg.netWorkMinutes; } } } return { 'total': totalMinutes, 'ordinary': ordinaryMinutes, 'overtime': overtimeMinutes, }; } }