using eSPJ.Models;

namespace eSPJ.Services
{
    public class DetailPenjemputanService
    {
        private readonly IDetailPenjemputanStore _store;
        private readonly IWebHostEnvironment _env;
        private readonly ILogger<DetailPenjemputanService> _logger;

        public DetailPenjemputanService(
            IWebHostEnvironment env,
            IDetailPenjemputanStore store,
            ILogger<DetailPenjemputanService> logger)
        {
            _env = env;
            _store = store;
            _logger = logger;
        }

        private static string SanitizePathSegment(string? value, string fallback = "umum")
        {
            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<List<TpsData>> GetAllTpsDataAsync()
        {
            return await _store.GetSubmittedAsync();
        }

        public async Task<List<TpsData>> GetRecordsByNomorSpjAsync(string nomorSpj)
        {
            return await _store.GetByNomorSpjAsync(nomorSpj);
        }

        public async Task<bool> SaveTpsDataAsync(List<TpsData> data)
        {
            try
            {
                foreach (var item in data)
                {
                    await _store.SaveSubmittedAsync(item);
                }
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error saving TPS data to JSON");
                return false;
            }
        }

        public async Task<DetailPenjemputanResponse> 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-umum");
                var tpsFolder = SanitizePathSegment(request.TpsName, "tps-1");
                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.TotalTimbangan = request.TotalTimbangan;
                tpsData.TotalOrganik = request.TotalOrganik;
                tpsData.TotalAnorganik = request.TotalAnorganik;
                tpsData.TotalResidu = request.TotalResidu;
                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<string>();
                    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<string>(existingRecord.FotoKedatangan);
                    tpsData.FotoKedatanganUploaded = existingRecord.FotoKedatanganUploaded || tpsData.FotoKedatangan.Count > 0;
                }
                else
                {
                    return new DetailPenjemputanResponse
                    {
                        Success = false,
                        Message = "Foto kedatangan harus diupload"
                    };
                }

                if (request.FotoTimbangan != null && request.FotoTimbangan.Any() && request.BeratTimbangan != null && request.JenisSampahList != null)
                {
                    tpsData.Timbangan = new List<TimbanganItem>();
                    for (int i = 0; i < request.FotoTimbangan.Count; i++)
                    {
                        var file = request.FotoTimbangan[i];
                        var fileName = $"timbangan_{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
                        var filePath = Path.Combine(uploadPath, fileName);
                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            await file.CopyToAsync(stream);
                        }

                        var jenisSampah = JenisSampah.Residu;
                        if (i < request.JenisSampahList.Count && Enum.TryParse<JenisSampah>(request.JenisSampahList[i], out var parsed))
                        {
                            jenisSampah = parsed;
                        }

                        tpsData.Timbangan.Add(new TimbanganItem
                        {
                            FotoFileName = $"{uploadBaseUrl}/{fileName}",
                            Berat = new List<decimal> { i < request.BeratTimbangan.Count ? request.BeratTimbangan[i] : 0 },
                            LokasiAngkut = new List<string>(),
                            JenisSampah = new List<JenisSampah> { jenisSampah },
                            IsUploaded = true,
                            WaktuUpload = DateTime.Now
                        });
                    }
                }
                else if (existingRecord?.Timbangan?.Any() == true)
                {
                    tpsData.Timbangan = existingRecord.Timbangan;
                }
                else
                {
                    return new DetailPenjemputanResponse
                    {
                        Success = false,
                        Message = "Foto timbangan harus diupload"
                    };
                }

                if (request.FotoPetugas != null && request.FotoPetugas.Any())
                {
                    tpsData.FotoPetugas = new List<string>();
                    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<string>(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}"
                };
            }
        }

        private Task<RecordSaveResponse> SaveRecordAsync(RecordSaveRequest request)
        {
            return SaveRecordInternalAsync(request);
        }

        private async Task<RecordSaveResponse> SaveRecordInternalAsync(RecordSaveRequest request)
        {
            try
            {
                await _store.SaveRecordAsync(request);

                return new RecordSaveResponse { Success = true, Message = "Data tersimpan." };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error saving penjemputan record");
                return new RecordSaveResponse { Success = false, Message = $"Gagal menyimpan data: {ex.Message}" };
            }
        }

        public async Task<RecordSaveResponse> SaveRecordNonTpsAsync(RecordSaveRequest request)
        {
            return await SaveRecordAsync(request);
        }

        public async Task<RecordSaveResponse> SaveRecordTpsAsync(RecordSaveRequest request)
        {
            return await SaveRecordAsync(request);
        }

        public async Task<List<TpsData>> GetSubmittedByNomorSpjAsync(string nomorSpj)
        {
            var normalizedNomorSpj = (nomorSpj ?? string.Empty).Trim();
            var allData = await _store.GetSubmittedAsync();
            return allData
                .Where(item => string.Equals((item.NomorSpj ?? string.Empty).Trim(), normalizedNomorSpj, StringComparison.OrdinalIgnoreCase))
                .OrderBy(item => item.SubmittedAt ?? DateTime.MinValue)
                .ToList();
        }

        public async Task<TpsData?> GetSubmittedDetailAsync(string nomorSpj, string? spjDetailId = null, string? lokasiAngkutId = null, string? namaTps = null)
        {
            return await _store.GetSubmittedDetailAsync(nomorSpj, spjDetailId, lokasiAngkutId, namaTps);
        }

        public async Task<TpsData?> 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)));
        }

        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<string>(source.FotoKedatangan ?? new List<string>()),
                FotoKedatanganUploaded = source.FotoKedatanganUploaded,
                Timbangan = (source.Timbangan ?? new List<TimbanganItem>()).Select(item => new TimbanganItem
                {
                    FotoFileName = item.FotoFileName,
                    Berat = new List<decimal>(item.Berat ?? new List<decimal>()),
                    LokasiAngkut = new List<string>(item.LokasiAngkut ?? new List<string>()),
                    JenisSampah = new List<JenisSampah>(item.JenisSampah ?? new List<JenisSampah>()),
                    IsUploaded = item.IsUploaded,
                    WaktuUpload = item.WaktuUpload
                }).ToList(),
                TotalOrganik = source.TotalOrganik,
                TotalAnorganik = source.TotalAnorganik,
                TotalResidu = source.TotalResidu,
                TotalTimbangan = source.TotalTimbangan,
                FotoPetugas = new List<string>(source.FotoPetugas ?? new List<string>()),
                FotoPetugasUploaded = source.FotoPetugasUploaded,
                NamaPetugas = source.NamaPetugas,
                IsSubmit = source.IsSubmit,
                UpdatedAt = source.UpdatedAt,
                SubmittedAt = source.SubmittedAt,
            };
        }

        public async Task<OcrTimbanganResponse> ProcessOcrTimbanganAsync(IFormFile foto)
        {
            try
            {
                await Task.Delay(500);

                return new OcrTimbanganResponse
                {
                    Success = true,
                    Weight = "54.50",
                    Raw = "54.50 kg",
                    Message = "OCR processed successfully (mock)"
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing OCR timbangan");
                return new OcrTimbanganResponse
                {
                    Success = false,
                    Message = $"Terjadi kesalahan: {ex.Message}"
                };
            }
        }
    }
}
