using eSPJ.Models; namespace eSPJ.Services { public class DetailPenjemputanJGCService { private readonly IDetailPenjemputanStore _store; private readonly IWebHostEnvironment _env; private readonly ILogger _logger; public DetailPenjemputanJGCService( IWebHostEnvironment env, IDetailPenjemputanStore store, ILogger logger) { _env = env; _store = store; _logger = logger; } private static string SanitizePathSegment(string? value, string fallback = "jgc") { var safe = string.Concat((value ?? string.Empty).Trim().Select(c => char.IsLetterOrDigit(c) || c == '-' || c == '_' ? c : '-')); while (safe.Contains("--")) { safe = safe.Replace("--", "-"); } safe = safe.Trim('-'); return string.IsNullOrWhiteSpace(safe) ? fallback : safe; } public async Task SubmitPenjemputanAsync(DetailPenjemputanRequest request) { try { if (string.IsNullOrEmpty(request.TpsName)) { return new DetailPenjemputanResponse { Success = false, Message = "Nama TPS harus diisi" }; } if (string.IsNullOrEmpty(request.NamaPetugas)) { return new DetailPenjemputanResponse { Success = false, Message = "Nama petugas harus diisi" }; } var existingRecord = await GetRecordDetailAsync(request.NomorSpj, request.SpjDetailId, request.LokasiAngkutId, request.TpsName); var now = DateTime.Now; var datePart = now.ToString("yyyy-MM-dd"); var spjFolder = SanitizePathSegment(request.NomorSpj, "spj-jgc"); var tpsFolder = SanitizePathSegment(request.TpsName, "tps-jgc"); var uploadPath = Path.Combine(_env.ContentRootPath, "uploads", "penjemputan", datePart, spjFolder, tpsFolder); var uploadBaseUrl = $"/uploads/penjemputan/{datePart}/{spjFolder}/{tpsFolder}"; if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } var tpsData = existingRecord != null ? CloneRecord(existingRecord) : new TpsData(); tpsData.NomorSpj = request.NomorSpj; tpsData.LokasiAngkutId = request.LokasiAngkutId; tpsData.SpjDetailId = request.SpjDetailId; tpsData.Name = request.TpsName; tpsData.Latitude = request.Latitude; tpsData.Longitude = request.Longitude; tpsData.AlamatJalan = request.AlamatJalan; tpsData.WaktuKedatangan = request.WaktuKedatangan; tpsData.NamaPetugas = request.NamaPetugas; tpsData.IsSubmit = true; tpsData.SubmittedAt ??= DateTime.Now; tpsData.UpdatedAt = DateTime.Now; if (request.FotoKedatangan != null && request.FotoKedatangan.Any()) { tpsData.FotoKedatangan = new List(); foreach (var file in request.FotoKedatangan) { var fileName = $"kedatangan_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; var filePath = Path.Combine(uploadPath, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } tpsData.FotoKedatangan.Add($"{uploadBaseUrl}/{fileName}"); } tpsData.FotoKedatanganUploaded = tpsData.FotoKedatangan.Count > 0; } else if (existingRecord?.FotoKedatangan?.Any() == true) { tpsData.FotoKedatangan = new List(existingRecord.FotoKedatangan); tpsData.FotoKedatanganUploaded = existingRecord.FotoKedatanganUploaded || tpsData.FotoKedatangan.Count > 0; } else { return new DetailPenjemputanResponse { Success = false, Message = "Foto kedatangan harus diupload" }; } if (request.FotoPetugas != null && request.FotoPetugas.Any()) { tpsData.FotoPetugas = new List(); foreach (var file in request.FotoPetugas) { var fileName = $"petugas_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; var filePath = Path.Combine(uploadPath, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } tpsData.FotoPetugas.Add($"{uploadBaseUrl}/{fileName}"); } tpsData.FotoPetugasUploaded = tpsData.FotoPetugas.Count > 0; } else if (existingRecord?.FotoPetugas?.Any() == true) { tpsData.FotoPetugas = new List(existingRecord.FotoPetugas); tpsData.FotoPetugasUploaded = existingRecord.FotoPetugasUploaded || tpsData.FotoPetugas.Count > 0; } else { return new DetailPenjemputanResponse { Success = false, Message = "Foto petugas harus diupload" }; } await _store.SaveSubmittedAsync(tpsData); return new DetailPenjemputanResponse { Success = true, Message = "Data penjemputan berhasil disimpan", Data = tpsData }; } catch (Exception ex) { _logger.LogError(ex, "Error submitting penjemputan data"); return new DetailPenjemputanResponse { Success = false, Message = $"Terjadi kesalahan: {ex.Message}" }; } } public async Task GetRecordDetailAsync(string nomorSpj, string? spjDetailId = null, string? lokasiAngkutId = null, string? namaTps = null) { var normalizedNomorSpj = (nomorSpj ?? string.Empty).Trim(); var normalizedSpjDetailId = (spjDetailId ?? string.Empty).Trim(); var normalizedLokasiAngkutId = (lokasiAngkutId ?? string.Empty).Trim(); var normalizedNamaTps = (namaTps ?? string.Empty).Trim(); var allData = await _store.GetByNomorSpjAsync(normalizedNomorSpj); return allData .OrderByDescending(item => item.UpdatedAt) .FirstOrDefault(item => (string.IsNullOrWhiteSpace(normalizedSpjDetailId) || string.Equals((item.SpjDetailId ?? string.Empty).Trim(), normalizedSpjDetailId, StringComparison.OrdinalIgnoreCase)) && (string.IsNullOrWhiteSpace(normalizedLokasiAngkutId) || string.Equals((item.LokasiAngkutId ?? string.Empty).Trim(), normalizedLokasiAngkutId, StringComparison.OrdinalIgnoreCase)) && (string.IsNullOrWhiteSpace(normalizedNamaTps) || string.Equals((item.Name ?? string.Empty).Trim(), normalizedNamaTps, StringComparison.OrdinalIgnoreCase))); } public async Task SaveRecordJGCAsync(RecordSaveRequest request) { try { await _store.SaveRecordAsync(request); return new RecordSaveResponse { Success = true, Message = "Data tersimpan." }; } catch (Exception ex) { _logger.LogError(ex, "Error saving JGC penjemputan record"); return new RecordSaveResponse { Success = false, Message = $"Gagal menyimpan data: {ex.Message}" }; } } private static TpsData CloneRecord(TpsData source) { return new TpsData { NomorSpj = source.NomorSpj, LokasiAngkutId = source.LokasiAngkutId, SpjDetailId = source.SpjDetailId, Name = source.Name, Index = source.Index, Latitude = source.Latitude, Longitude = source.Longitude, AlamatJalan = source.AlamatJalan, WaktuKedatangan = source.WaktuKedatangan, FotoKedatangan = new List(source.FotoKedatangan ?? new List()), FotoKedatanganUploaded = source.FotoKedatanganUploaded, FotoPetugas = new List(source.FotoPetugas ?? new List()), FotoPetugasUploaded = source.FotoPetugasUploaded, NamaPetugas = source.NamaPetugas, IsSubmit = source.IsSubmit, UpdatedAt = source.UpdatedAt, SubmittedAt = source.SubmittedAt, }; } } }