
using AutoMapper;
using DocumentFormat.OpenXml.InkML;
using Microsoft.EntityFrameworkCore;
using Serilog;
using System.Collections.Generic;
using WorkFlowCheck.BL.Services.Interfaces;
using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.Common.Enums;
using WorkFlowCheck.DL;
using WorkFlowCheck.DL.Entities;

namespace WorkFlowCheck.BL.Services
{
    public class SyncService : BaseService, ISyncService
    {
        public SyncService(AppDbContext dbContext, IMapper mapper) : base(dbContext, mapper) { }

        public async Task<List<CheckPointDTO>> GetAllCheckPointAsync()
        {
            var retVal = new List<CheckPointDTO>();

            try
            {
                var res = await _dbContext.CheckPoints
                                         .Include(i => i.CheckListTemplateRows)
                                         .AsNoTracking()
                                         .ToListAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<List<CheckPointDTO>>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<CheckPointDTO> GetCheckPointAsync(int id)
        {
            var retVal = new CheckPointDTO();

            try
            {
                var res = await _dbContext.CheckPoints
                                         .Include(i => i.CheckListTemplateRows)
                                         .Where(w => w.Id == id)
                                         .AsNoTracking()
                                         .FirstOrDefaultAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<CheckPointDTO>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<bool> DeleteCheckPointAsync(int id)
        {
            return await DeleteEntityByIdAsync<CheckPoint>(id);
        }
        public async Task<CheckPointDTO> UpdateCheckPointAsync(CheckPointDTO checkPointDTO)
        {
            var retVal = new CheckPointDTO();

            try
            {
                if (checkPointDTO.Id == 0) //Hozzáadás, ha Id == 0
                {
                    var checkPoint = _mapper.Map<CheckPoint>(checkPointDTO);
                    _dbContext.CheckPoints.Add(checkPoint);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<CheckPointDTO>(checkPoint);
                }
                else
                {
                    var res = await _dbContext.CheckPoints.Where(w => w.Id == checkPointDTO.Id).FirstOrDefaultAsync();
                    if (res != null)
                    {
                        res.ShortName = checkPointDTO.ShortName;
                        res.Code = checkPointDTO.Code;
                        res.IsEnabled = checkPointDTO.IsEnabled;

                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<CheckPointDTO>(res);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<List<CheckPointDTO>> UpdateAllCheckPointAsync(List<CheckPointDTO> checkPointListDTO)
        {
            var retVal = new List<CheckPointDTO>();
            try
            {
                var ids = checkPointListDTO.Select(dto => dto.Id).ToList();
                var checkPoints = await _dbContext.CheckPoints
                    .Where(cp => ids.Contains(cp.Id))
                    .ToListAsync();

                foreach (var checkPoint in checkPoints)
                {
                    var dto = checkPointListDTO.FirstOrDefault(d => d.Id == checkPoint.Id);
                    if (dto != null)
                    {
                        checkPoint.Code = dto.Code;
                    }
                }
                await _dbContext.SaveChangesAsync();
                retVal = _mapper.Map<List<CheckPointDTO>>(checkPoints);
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }

        public async Task<List<LocationDTO>> GetAllLocationAsync()
        {
            var retVal = new List<LocationDTO>();

            try
            {
                var res = await _dbContext.Locations.ToListAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<List<LocationDTO>>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<LocationDTO> GetLocationAsync(int id)
        {
            var retVal = new LocationDTO();

            try
            {
                var res = await _dbContext.Locations
                                         .Where(w => w.Id == id)
                                         .AsNoTracking()
                                         .FirstOrDefaultAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<LocationDTO>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<bool> DeleteLocationAsync(int id)
        {
            return await DeleteEntityByIdAsync<Location>(id);
        }
        public async Task<LocationDTO> UpdateLocationAsync(LocationDTO LocationDTO)
        {
            var retVal = new LocationDTO();

            try
            {
                if (LocationDTO.Id == 0) //Hozzáadás, ha Id == 0
                {
                    var Location = _mapper.Map<Location>(LocationDTO);
                    _dbContext.Locations.Add(Location);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<LocationDTO>(Location);
                }
                else
                {
                    var res = await _dbContext.Locations.Where(w => w.Id == LocationDTO.Id).FirstOrDefaultAsync();
                    if (res != null)
                    {
                        res = _mapper.Map<Location>(LocationDTO);

                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<LocationDTO>(res);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<List<EquipmentDTO>> GetAllEquipmentAsync()
        {
            var retVal = new List<EquipmentDTO>();

            try
            {
                var res = await _dbContext.Equipments.ToListAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<List<EquipmentDTO>>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<EquipmentDTO> GetEquipmentAsync(int id)
        {
            var retVal = new EquipmentDTO();

            try
            {
                var res = await _dbContext.Equipments
                                         .Where(w => w.Id == id)
                                         .AsNoTracking()
                                         .FirstOrDefaultAsync();
                if (res != null)
                {
                    retVal = _mapper.Map<EquipmentDTO>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<bool> DeleteEquipmentAsync(int id)
        {
            return await DeleteEntityByIdAsync<Equipment>(id);
        }
        public async Task<EquipmentDTO> UpdateEquipmentAsync(EquipmentDTO EquipmentDTO)
        {
            var retVal = new EquipmentDTO();

            try
            {
                if (EquipmentDTO.Id == 0) //Hozzáadás, ha Id == 0
                {
                    var Equipment = _mapper.Map<Equipment>(EquipmentDTO);
                    _dbContext.Equipments.Add(Equipment);
                    await _dbContext.SaveChangesAsync();

                    retVal = _mapper.Map<EquipmentDTO>(Equipment);
                }
                else
                {
                    var res = await _dbContext.Equipments.Where(w => w.Id == EquipmentDTO.Id).FirstOrDefaultAsync();
                    if (res != null)
                    {
                        res.ShortName = EquipmentDTO.ShortName;
                        res.EquipmentNumber = EquipmentDTO.EquipmentNumber;

                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<EquipmentDTO>(res);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<List<CheckListTemplateHeaderDTO>> GetAllCheckListTemplateAsync(int userId)
        {
            var retVal = new List<CheckListTemplateHeaderDTO>();

            try
            {
                var user = _dbContext.Users.Where(w => w.Id == userId).FirstOrDefault();
                if (user != null)
                {
                    var res = await (from ur in _dbContext.UserRoles
                                     join rth in _dbContext.RoleCheckListTemplateHeaders on ur.RoleId equals rth.RoleId
                                     join header in _dbContext.CheckListTemplateHeaders on rth.CheckListTemplateHeaderId equals header.Id
                                     where ur.UserId == userId
                                     select header)
                                .Include(h => h.CheckListTemplateRows)
                                .Distinct()
                                .AsNoTracking()
                                .ToListAsync();

                    if (res != null)
                    {
                        retVal = _mapper.Map<List<CheckListTemplateHeaderDTO>>(res);

                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<List<CheckListHeaderDTO>> GetAllCheckListAsync(int userId)
        {
            var retVal = new List<CheckListHeaderDTO>();

            try
            {
                var res = await _dbContext.CheckListHeaders
                                          .Where(w => w.IsEditable &&
                                                      w.UserId == userId &&
                                                      w.IsDeleted != true &&
                                                      (w.CheckStatus == CheckStatus.InProgress ||
                                                       w.CheckStatus == CheckStatus.Open))
                                          .Include(i => i.CheckListRows)
                                          //.ThenInclude(i => i.CheckListTemplateRow)
                                          .AsNoTracking()
                                          .ToListAsync();

                if (res != null)
                {
                    retVal = _mapper.Map<List<CheckListHeaderDTO>>(res);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<CheckListHeaderDTO> UpdateCheckListHeaderAsync(CheckListHeaderDTO checkListHeaderDTO)
        {
            var retVal = new CheckListHeaderDTO();

            try
            {
                if (checkListHeaderDTO.Id == 0) //Hozzáadás, ha Id == 0
                {

                }
                else
                {
                    var res = await _dbContext.CheckListHeaders
                                              .Include(i => i.CheckListRows)
                                              .Where(w => w.Id == checkListHeaderDTO.Id)
                                              .FirstOrDefaultAsync();
                    if (res != null)
                    {
                        var ids = checkListHeaderDTO.CheckListRowDTO?.Select(r => r.Id).ToList();
                        if (ids != null && ids.Count > 0)
                        {
                            var rowsToUpdate = await _dbContext.CheckListRows
                                                    .Where(r => ids.Contains(r.Id))
                                                    .ToListAsync();
                            foreach (var row in rowsToUpdate)
                            {
                                var dtoRow = checkListHeaderDTO.CheckListRowDTO?.FirstOrDefault(r => r.Id == row.Id);
                                if (dtoRow != null)
                                {
                                    row.Answer = dtoRow.Answer;
                                    if (dtoRow.Photo != null && dtoRow.Photo.Length > 0)
                                    {
                                        string imageDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Images");
                                        var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                                        var fileName = $"PH_{timestamp}_{row.CheckListHeaderId}_{row.Id}.jpeg";
                                        row.PhotoFileName = fileName;
                                        var filePath = Path.Combine(imageDirectory, fileName);
                                        await File.WriteAllBytesAsync(filePath, dtoRow.Photo);
                                    }
                                }
                            }
                        }
                        await _dbContext.SaveChangesAsync();

                        retVal = _mapper.Map<CheckListHeaderDTO>(res);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
    }
}
