using Android.Content;
using Android.Util;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
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 static Android.Renderscripts.ScriptGroup;
using Location = WorkFlowCheck.MAUI.DataLayer.Entities.Location;

namespace WorkFlowCheck.MAUI.Services
{
    public class SyncService : BaseService, ISyncService
    {
        private readonly IUserService _userService;

        public SyncService(HttpClient httpClient, AppDbContext dbContext, IMapper mapper, IUserService userService) : base(httpClient, 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);
            await SyncUsers_Down(reportProgress);
        }
        public async Task DownloadAPK(Action<double, string> reportProgress)
        {
            try
            {
                await PrepareAuthenticatedRequestAsync();
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/Download";

                string fileName = "com.nuvolar.wfcapp-Signed.apk";

                // Az Androidon lévő privát letöltési mappa
                string downloadFolder = Path.Combine(Android.App.Application.Context.GetExternalFilesDir(null)?.AbsolutePath, "APK");

                // Ellenőrizd, hogy a mappa létezik-e, ha nem, hozd létre
                if (!Directory.Exists(downloadFolder))
                {
                    Directory.CreateDirectory(downloadFolder);
                }

                string filePath = Path.Combine(downloadFolder, fileName);

                using (_httpClient)
                {
                    var response = await _httpClient.GetAsync(endpoint, HttpCompletionOption.ResponseHeadersRead);
                    if (response.IsSuccessStatusCode)
                    {
                        var totalBytes = response.Content.Headers.ContentLength ?? -1L;
                        long receivedBytes = 0;

                        using (var stream = await response.Content.ReadAsStreamAsync())
                        using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            byte[] buffer = new byte[1024 * 1024]
;
                            int bytesRead;

                            while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                            {
                                await fileStream.WriteAsync(buffer, 0, bytesRead);
                                receivedBytes += bytesRead;

                                if (totalBytes != -1)
                                {
                                    double progress = (double)receivedBytes / totalBytes * 100;
                                    reportProgress(progress, $"APK letöltés...");
                                }
                                else
                                {
                                    reportProgress(-1, $"APK letöltés...");
                                }
                            }
                        }

                        // Telepítés indítása a FileProvider segítségével
                        //var apkUri = FileProvider.GetUriForFile(Android.App.Application.Context,
                        //    $"{Android.App.Application.Context.PackageName}.fileprovider",
                        //    new Java.IO.File(filePath));

                        //var installIntent = new Intent(Intent.ActionView);
                        //installIntent.SetDataAndType(apkUri, "application/vnd.android.package-archive");
                        //installIntent.AddFlags(ActivityFlags.NewTask);
                        //installIntent.AddFlags(ActivityFlags.GrantReadUriPermission);

                        //Android.App.Application.Context.StartActivity(installIntent);
                    }
                    else
                    {
                        reportProgress(0, $"Letöltési hiba: {response.StatusCode}");
                        Console.WriteLine($"Letöltési hiba: {response.StatusCode}");
                    }
                }
            }
            catch (Exception ex)
            {
                reportProgress(0, $"Hiba történt: {ex.Message}");
                Console.WriteLine($"Hiba történt: {ex.Message}");
            }
        }

        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<ApiResponseDTO<string>> SyncCheckPoints_Up(Action<double, string> reportProgress)
        {
            var retVal = new ApiResponseDTO<string>();
            try
            {
                await PrepareAuthenticatedRequestAsync();

                var checkPointList = await _dbContext.CheckPoints.ToListAsync();

                var checkPointListDTO = _mapper.Map<List<CheckPointDTO>>(checkPointList);
                var endpoint = $"{_httpClient.BaseAddress}api/Sync/UpdateAllCheckPoint";

                var json = JsonConvert.SerializeObject(checkPointListDTO, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                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 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++;
                    }

                    foreach (var checkListHeaderDTO in responseList.Data)
                    {
                        var checkListHeader = await _dbContext.CheckListHeaders.Where(w => w.Id == checkListHeaderDTO.Id).FirstOrDefaultAsync();
                        if (checkListHeader != null)
                        {
                            checkListHeader.CheckStatus = checkListHeaderDTO.CheckStatus;
                            await _dbContext.SaveChangesAsync();

                            //foreach (var checkListRow in checkListHeader.CheckListRows)
                            //{
                            //    var checkListRowDTO = checkListHeaderDTO.CheckListRowDTO.Where(w => w.GuidNumber == checkListRow.GuidNumber).FirstOrDefault();
                                
                            //    if (checklistrow{

                            //    }
                            //}
                        }
                    }
                }
            }
            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)
                                                        .ThenInclude(i => i.CheckListTemplateRow)
                                                        .ThenInclude(i => i.CheckPoint)
                                                    .AsNoTracking()
                                                    .FirstOrDefaultAsync();

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

                var json = JsonConvert.SerializeObject(checkListHeaderDTO, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                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;
        }

        public async Task<List<DeviceMessageDTO>> DeviceMessageReadUnreaded(string deviceId)
        {
            var deviceIdBase64 = Base64UrlEncoder.Encode(Encoding.UTF8.GetBytes(deviceId));
            string endpoint = $"{_httpClient.BaseAddress}api/Sync/DeviceMessageReadUnreaded/{deviceIdBase64}";
            var retVal = new List<DeviceMessageDTO>();
            try
            {
                var response = await _httpClient.GetFromJsonAsync<ApiResponseDTO<List<DeviceMessageDTO>>>(endpoint);
                if (response != null)
                {
                    if (response.IsSuccess)
                    {
                        return response.Data;
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return retVal;
        }
        public async Task<List<DeviceMessageDTO>> DeviceMessageReadUnreadedRole(int roleId)
        {
            string endpoint = $"{_httpClient.BaseAddress}api/Sync/DeviceMessageReadUnreadedRole/{roleId}";
            var retVal = new List<DeviceMessageDTO>();
            try
            {
                var response = await _httpClient.GetFromJsonAsync<ApiResponseDTO<List<DeviceMessageDTO>>>(endpoint);
                if (response != null)
                {
                    if (response.IsSuccess)
                    {
                        return response.Data;
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return retVal;
        }

        public async Task<ApiResponseDTO<string>> SyncUsers_Up(Action<double, string> reportProgress)
        {
            var retVal = new ApiResponseDTO<string>();
            try
            {
                await PrepareAuthenticatedRequestAsync();

                var userList = await _dbContext.MobileUsers.ToListAsync();

                var mobileUserListDTO = _mapper.Map<List<MobileUserDTO>>(userList);
                var endpoint = $"{_httpClient.BaseAddress}api/Sync/UpdateAllMobileUser";

                var json = JsonConvert.SerializeObject(mobileUserListDTO, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                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 SyncUsers_Down(Action<double, string> reportProgress)
        {
            try
            {
                string endpoint = $"{_httpClient.BaseAddress}api/Sync/GetAllMobileUsers";
                var responseList = DownloadDataAsync<MobileUserDTO>(endpoint, reportProgress).Result;

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

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

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

            }
        }

        public async Task<ApiResponseDTO<bool>> UploadFCMToken(string token)
        {
            var retVal = new ApiResponseDTO<bool>();    
            try
            {
                string endpoint = $"{_httpClient.BaseAddress}api/fcm/SendFCMToken";

                var FCMMessageDTO = new FCMMessageDTO()
                {
                    Token = token,
                    UserId = _userService.GetCurrentUser()?.Id
                };  
                using (HttpResponseMessage httpResponseMessage = await _httpClient.PostAsJsonAsync(endpoint, FCMMessageDTO))
                {
                    httpResponseMessage.EnsureSuccessStatusCode();

                    var jsonString = await httpResponseMessage.Content.ReadAsStringAsync();
                    var response = JsonConvert.DeserializeObject<ApiResponseDTO<bool>>(jsonString);

                    return response ?? new ApiResponseDTO<bool>
                    {
                        IsSuccess = false,
                    };
                }
            }
            catch (Exception ex)
            {
                // Hiba visszaadása
                return new ApiResponseDTO<bool>
                {
                    IsSuccess = false
                };
            }
        }
    }
}
