import 'dart:async'; import 'package:pocketbase/pocketbase.dart'; import '../../../core/api/pocketbase_client.dart'; import '../../../core/services/finance_service.dart'; import '../../../core/services/job_history_service.dart'; import '../../../models/job.dart'; const _listExpand = 'clinic_tenant_id,lab_tenant_id,patient_id'; const _detailExpand = 'clinic_tenant_id,lab_tenant_id,patient_id,prosthetic_id'; class LabJobsRepository { LabJobsRepository._(); static final instance = LabJobsRepository._(); PocketBase get _pb => PocketBaseClient.instance.pb; Future> listInbound( String labTenantId, { String? status, int page = 1, int limit = 30, }) async { final filterParts = ['lab_tenant_id = "$labTenantId"']; if (status != null) filterParts.add('status = "$status"'); final result = await _pb.collection('jobs').getList( page: page, perPage: limit, filter: filterParts.join(' && '), expand: _listExpand, sort: '-created', ); return (result.items.map((r) => Job.fromJson(r.toJson())).toList() ..sort((a, b) => b.dateCreated.compareTo(a.dateCreated))); } Future> listInProgress(String labTenantId, {int limit = 50, String? location}) async { final filterParts = [ 'lab_tenant_id = "$labTenantId"', 'status = "in_progress"' ]; if (location != null) filterParts.add('location = "$location"'); final result = await _pb.collection('jobs').getList( perPage: limit, filter: filterParts.join(' && '), expand: _listExpand, sort: location == null ? '-created' : null, ); return (result.items.map((r) => Job.fromJson(r.toJson())).toList() ..sort((a, b) { if (a.dueDate == null && b.dueDate == null) { return b.dateCreated.compareTo(a.dateCreated); } if (a.dueDate == null) return 1; if (b.dueDate == null) return -1; final cmp = a.dueDate!.compareTo(b.dueDate!); return cmp != 0 ? cmp : b.dateCreated.compareTo(a.dateCreated); })); } Future getJob(String jobId) async { final record = await _pb.collection('jobs').getOne(jobId, expand: _detailExpand); return Job.fromJson(record.toJson()); } Future acceptJob(Job pendingJob) async { final firstStep = pendingJob.stepTemplate.first; final record = await _pb.collection('jobs').update(pendingJob.id, body: { 'status': 'in_progress', 'current_step': firstStep.value, 'location': 'at_lab', }); final job = Job.fromJson(record.toJson()); unawaited(JobHistoryService.instance.append( jobId: pendingJob.id, clinicTenantId: job.clinicTenantId, labTenantId: job.labTenantId, action: JobHistoryAction.accepted, step: firstStep, )); return job; } Future handToClinic(String jobId, Job job, {required bool finish, required String note}) async { if (note.trim().isEmpty) { throw ArgumentError('Aşama açıklaması gereklidir.'); } final dispatchStep = job.labDispatchStep(finish: finish); final steps = [...job.stepTemplate]; if (!steps.contains(dispatchStep)) { steps.insert(0, dispatchStep); } final patch = { 'status': finish ? 'sent' : 'in_progress', 'location': 'at_clinic', 'current_step': dispatchStep.value, 'workflow_steps': steps.map((step) => step.value).toList(), }; final record = await _pb.collection('jobs').update(jobId, body: patch); final updated = Job.fromJson(record.toJson()); await JobHistoryService.instance.append( jobId: jobId, clinicTenantId: job.clinicTenantId, labTenantId: job.labTenantId, action: JobHistoryAction.handedToClinic, step: dispatchStep, note: '${finish ? "Bitime gönderildi" : "Provaya gönderildi"}: ${note.trim()}', ); return updated; } Future cancelJob(String jobId, Job job) async { final record = await _pb.collection('jobs').update(jobId, body: { 'status': 'cancelled', }); await FinanceService.instance.deletePendingEntriesForJob(jobId); unawaited(JobHistoryService.instance.append( jobId: jobId, clinicTenantId: job.clinicTenantId, labTenantId: job.labTenantId, action: JobHistoryAction.cancelled, step: job.currentStep, )); return Job.fromJson(record.toJson()); } Future bulkAcceptPending(String labTenantId) async { final pending = await listInbound(labTenantId, status: 'pending', limit: 200); await Future.wait(pending.map((j) => acceptJob(j))); } Future countByStatus(String labTenantId, String? status) async { final filter = status != null ? 'lab_tenant_id = "$labTenantId" && status = "$status"' : 'lab_tenant_id = "$labTenantId"'; final r = await _pb.collection('jobs').getList(perPage: 1, filter: filter); return r.totalItems; } Future countDelivered(String labTenantId, {DateTime? from, DateTime? to}) async { final parts = ['lab_tenant_id = "$labTenantId"', 'status = "delivered"']; if (from != null) parts.add('updated >= "${_date(from)}"'); if (to != null) parts.add('updated < "${_date(to)}"'); final r = await _pb .collection('jobs') .getList(perPage: 1, filter: parts.join(' && ')); return r.totalItems; } static String _date(DateTime d) => d.toIso8601String().split('T').first; }