using Android.Health.Connect.DataTypes.Units;
using AutoMapper;
using Java.Net;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text;
using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.MAUI.DataLayer;
using WorkFlowCheck.MAUI.DataLayer.Entities;
using WorkFlowCheck.MAUI.Handlers;
using WorkFlowCheck.MAUI.Services.Interfaces;
using Location = WorkFlowCheck.MAUI.DataLayer.Entities.Location;

namespace WorkFlowCheck.MAUI.Services
{
    public class SyncService : BaseService, ISyncService
    {
        private readonly IUserService _userService;
        public SyncService(HttpClient httpClient, IConfiguration configuration, AppDbContext dbContext, IMapper mapper, IUserService userService) : base(httpClient, configuration, dbContext, mapper)
        {
            _userService = userService;
        }
        public async Task SyncDatas(Action<double, string> reportProgress)
        {
            await SyncCheckPoints_Down(reportProgress);
            await SyncLocations_Down(reportProgress);
            await SyncEquipments_Down(reportProgress);
            await SyncCheckListTemplates_Down(reportProgress);
            await SyncCheckListHeader_Down(reportProgress);
        }
        public async Task SyncCheckPoints_Down(Action<double, string> reportProgress)
        {
            try
            {
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllCheckPoints";
                var responseList = DownloadDataAsync<CheckPointDTO>(endpoint, reportProgress).Result;

                if (responseList != null)
                {
                    if (responseList.IsSuccess)
                    {
                        var entityList = await _dbContext.CheckPoints.ToListAsync();
                        var missingItems = responseList.Data.Where(f => !entityList.Any(s => s.Id == f.Id)).ToList();

                        var mappedMissingItems = _mapper.Map<List<CheckPoint>>(missingItems);

                        _dbContext.CheckPoints.AddRange(mappedMissingItems);
                        await _dbContext.SaveChangesAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Hiba történt: {ex.Message}");
            }
        }
        public async Task SyncCheckPoints_Up(Action<double, string> reportProgress)
        {
            try
            {

            }
            catch (Exception ex)
            {
                // Hiba visszaadása
            }
        }

        public async Task SyncLocations_Down(Action<double, string> reportProgress)
        {
            try
            {
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllLocations";
                var responseList = DownloadDataAsync<LocationDTO>(endpoint, reportProgress).Result;

                if (responseList != null)
                {
                    if (responseList.IsSuccess)
                    {
                        var entityList = await _dbContext.Locations.ToListAsync();
                        var missingItems = responseList.Data.Where(f => !entityList.Any(s => s.Id == f.Id)).ToList();

                        var mappedMissingItems = _mapper.Map<List<Location>>(missingItems);

                        _dbContext.Locations.AddRange(mappedMissingItems);
                        await _dbContext.SaveChangesAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                // Hiba visszaadása

            }
        }
        public async Task SyncEquipments_Down(Action<double, string> reportProgress)
        {
            try
            {
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllEquipments";
                var responseList = DownloadDataAsync<LocationDTO>(endpoint, reportProgress).Result;

                if (responseList != null)
                {
                    if (responseList.IsSuccess)
                    {
                        var entityList = await _dbContext.Locations.ToListAsync();
                        var missingItems = responseList.Data.Where(f => !entityList.Any(s => s.Id == f.Id)).ToList();

                        var mappedMissingItems = _mapper.Map<List<Equipment>>(missingItems);

                        _dbContext.Equipments.AddRange(mappedMissingItems);
                        await _dbContext.SaveChangesAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                // Hiba visszaadása

            }
        }
        public async Task SyncCheckListTemplates_Down(Action<double, string> reportProgress)
        {
            try
            {
                var userId = _userService.GetCurrentUser()?.Id;
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllCheckListTemplateHeader/{userId}";
                var responseList = DownloadDataAsync<CheckListTemplateHeaderDTO>(endpoint, reportProgress).Result;

                if (responseList != null)
                {
                    if (responseList.IsSuccess)
                    {
                        var checkListTemplateHeaderList = await _dbContext.CheckListTemplateHeaders.ToListAsync();
                        var missingItems = responseList.Data.Where(f => !checkListTemplateHeaderList.Any(s => s.Id == f.Id)).ToList();

                        var missingCheckListTemplateHeaders = _mapper.Map<List<CheckListTemplateHeader>>(missingItems);

                        _dbContext.CheckListTemplateHeaders.AddRange(missingCheckListTemplateHeaders);
                        await _dbContext.SaveChangesAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                // Hiba visszaadása

            }
        }


        public async Task SyncCheckListHeader_Down(Action<double, string> reportProgress)
        {
            try
            {
                var userId = _userService.GetCurrentUser()?.Id;
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllCheckListHeader/{userId}";
                var responseList = DownloadDataAsync<CheckListHeaderDTO>(endpoint, reportProgress).Result;

                if (responseList != null && responseList.IsSuccess)
                {
                    var checkListHeaderList = await _dbContext.CheckListHeaders.ToListAsync();
                    var missingItems = responseList.Data
                        .Where(f => !checkListHeaderList.Any(s => s.GuidNumber == f.GuidNumber))
                        .ToList();

                    var missingCheckListHeaders = _mapper.Map<List<CheckListHeader>>(missingItems);
                    _dbContext.CheckListHeaders.AddRange(missingCheckListHeaders);
                    await _dbContext.SaveChangesAsync();

                    int i = 1;
                    foreach (var item in missingItems)
                    {
                        double itemPercentage = (double)i / missingItems.Count * 100;
                        reportProgress(itemPercentage, "Adatbázis szinkronizáció...");  // Közvetlen progress jelentés
                        i++;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Hiba történt: {ex.Message}");
            }
        }
        public async Task<ApiResponseDTO<string>> SyncCheckListHeader_Up(int Id, Action<double, string> reportProgress)
        {
            var retVal = new ApiResponseDTO<string>();
            try
            {
                await PrepareAuthenticatedRequestAsync();

                var checkListHeader = await _dbContext.CheckListHeaders
                                                    .Where(w => w.Id == Id)
                                                    .Include(i => i.CheckListRows)
                                                    .AsNoTracking()
                                                    .FirstOrDefaultAsync();

                var checkListHeaderDTO = _mapper.Map<CheckListHeaderDTO>(checkListHeader);
                var endpoint = $"{_httpClient.BaseAddress}api/Sync/UpdateCheckListHeader";

                var json = JsonConvert.SerializeObject(checkListHeaderDTO);
                var jsonBytes = Encoding.UTF8.GetBytes(json);
                var jsonStream = new MemoryStream(jsonBytes);

                var progressContent = new ProgressableStreamContent(jsonStream, 8192, (uploaded, total) =>
                {
                    double percentage = (double)uploaded / total * 100;
                    reportProgress(percentage, "Beküldés...");
                });

                progressContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

                using (HttpResponseMessage httpResponseMessage = await _httpClient.PostAsync(endpoint, progressContent))
                {
                    httpResponseMessage.EnsureSuccessStatusCode();
                    var jsonString = await httpResponseMessage.Content.ReadAsStringAsync();
                    retVal = JsonConvert.DeserializeObject<ApiResponseDTO<string>>(jsonString);
                }

            }
            catch (Exception ex)
            {
                retVal.IsSuccess = false;
                retVal.Errors.Add(ex.Message);  
            }
            return retVal;
        }

        public async Task<ApiResponseDTO<List<T>>> DownloadDataAsync<T>(string endpoint, Action<double, string> reportProgress)
        {
            await PrepareAuthenticatedRequestAsync();

            using var response = await _httpClient.GetAsync(endpoint, HttpCompletionOption.ResponseHeadersRead);
            response.EnsureSuccessStatusCode();

            using var stream = await response.Content.ReadAsStreamAsync();
            using var memoryStream = new MemoryStream();

            var buffer = new byte[8192];
            long totalRead = 0;
            int bytesRead;
            int chunkCounter = 0;

            while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await memoryStream.WriteAsync(buffer, 0, bytesRead);
                totalRead += bytesRead;
                chunkCounter++;

                // Gyakori progress frissítés
                if (chunkCounter % 5 == 0) // 5 blokk után
                {
                    double estimatedProgress = Math.Min((double)totalRead / (8192 * 100) * 100, 99);
                    reportProgress(estimatedProgress, "Letöltés ...");
                }
            }

            // Végső progress 100%-ra állítása
            reportProgress(100, "Letöltés ... kész!");

            memoryStream.Position = 0;
            var jsonString = Encoding.UTF8.GetString(memoryStream.ToArray());

            // Generikus deszerializálás
            var responseList = JsonConvert.DeserializeObject<ApiResponseDTO<List<T>>>(jsonString);
            return responseList;
        }
    }
}
