using AutoMapper;
using DocumentFormat.OpenXml.Office.CustomUI;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Serilog;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCheck.BL.DocumentGenerator;
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 CheckListService : ICheckListService
    {
        private readonly AppDbContext _dbContext;
        private readonly IMapper _mapper;
        private readonly INumberGeneratorService _numberGeneratorService;

        public CheckListService(AppDbContext dbContext, IMapper mapper, INumberGeneratorService numberGeneratorService)
        {
            _dbContext = dbContext;
            _mapper = mapper;
            _numberGeneratorService = numberGeneratorService;
        }

        public async Task<CheckListHeaderDTO> GetCheckListHeaderAsync(int Id)
        {
            var retVal = new CheckListHeaderDTO()
            {
                CheckListRowDTO = new List<CheckListRowDTO>()
            };

            try
            {
                var res = await _dbContext.CheckListHeaders
                                       .Where(w => w.Id == Id)
                                       .Include(i => i.CheckListRows)
                                            .ThenInclude(r => r.CheckListTemplateRow)
                                                .ThenInclude(r => r.CheckPoint)
                                       .Include(i => i.CheckListRows)
                                            .ThenInclude(r => r.CheckListTemplateRow)
                                                .ThenInclude(r => r.Equipment)
                                       .AsNoTracking()
                                       .FirstOrDefaultAsync();
                if (res != null)
                {
                    res.CheckListRows = res.CheckListRows
                                    .OrderBy(r => r.CheckListTemplateRow.CheckPoint?.ShortName ?? string.Empty)
                                    .ThenBy(r => r.CheckListTemplateRow.RowIndex)
                                    .ToList();


                }
                if (res != null)
                {
                    retVal = _mapper.Map<CheckListHeaderDTO>(res);

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

            return retVal;
        }
        public async Task<List<CheckListHeaderDTO>> GetAllCheckListHeaderAsync()
        {
            var retVal = new List<CheckListHeaderDTO>();
            try
            {
                var roles = await _dbContext.CheckListHeaders
                                            .Include(i => i.CheckListRows)
                                            .Include(i => i.User)
                                            .AsNoTracking()
                                            .ToListAsync();
                if (roles != null)
                {
                    retVal = _mapper.Map<List<CheckListHeaderDTO>>(roles);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<CheckListHeaderDTO> UpdateCheckListHeaderAsync(CheckListHeaderDTO checkListHeaderDTO)
        {
            var retVal = new CheckListHeaderDTO() { CheckListRowDTO = new List<CheckListRowDTO>() };
            try
            {
                if (checkListHeaderDTO.Id == 0)
                {
                    var checkListHeader = new CheckListHeader()
                    {
                        CheckListTemplateHeaderId = checkListHeaderDTO.CheckListTemplateHeaderDTO.Id,
                        Description = checkListHeaderDTO.Description,
                        GuidNumber = Guid.NewGuid(),
                    };
                    _dbContext.CheckListHeaders.Add(checkListHeader);
                    await _dbContext.SaveChangesAsync();
                    retVal = _mapper.Map<CheckListHeaderDTO>(checkListHeader);
                }
                else
                {
                    var checkListHeader = await _dbContext.CheckListHeaders
                                            .Include(i => i.CheckListRows)
                                            .Where(w => w.Id == checkListHeaderDTO.Id)
                                            .FirstOrDefaultAsync();
                    if (checkListHeader != null)
                    {
                        checkListHeader.Description = checkListHeaderDTO.Description;


                        await _dbContext.SaveChangesAsync();
                        retVal = _mapper.Map<CheckListHeaderDTO>(checkListHeader);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }
        public async Task<CheckListHeaderDTO> StartNewCheckListAsync(CheckListHeaderNewDTO checkListHeaderNewDTO)
        {
            var retVal = new CheckListHeaderDTO()
            {
                CheckListRowDTO = new List<CheckListRowDTO>()
            };
            using var transaction = await _dbContext.Database.BeginTransactionAsync();
            try
            {
                var checkListTemplateHeader = await _dbContext.CheckListTemplateHeaders
                                                             .Where(w => w.Id == checkListHeaderNewDTO.CheckListTemplateHeaderId)
                                                             .FirstOrDefaultAsync();
                if (checkListTemplateHeader == null)
                {
                    return retVal;
                }
                var currentDate = DateTime.UtcNow;
                var documentNumber = await _numberGeneratorService.GenerateNextNumberAsync(checkListTemplateHeader.NumberGenerator1Id ?? 1, transaction, currentDate);
                CheckListHeader checkListHeader = new CheckListHeader()
                {
                    CheckListTemplateHeaderId = checkListHeaderNewDTO.CheckListTemplateHeaderId,
                    CheckStatus = CheckStatus.Open,
                    DateExecution = currentDate,
                    IsEditable = true,
                    UserId = checkListHeaderNewDTO.UserId,
                    ShortName = "",
                    Description = "",
                    DocumentNumber = documentNumber,
                    GuidNumber = Guid.NewGuid(),
                    IsDeleted = false,
                    IsStorno = false,
                    CheckListRows = new List<CheckListRow>()
                };


                _dbContext.CheckListHeaders.Add(checkListHeader);
                await _dbContext.SaveChangesAsync();

                var checkListTemplateRows = await _dbContext.CheckListTemplateRows
                                                    .Where(w => w.CheckListTemplateHeaderId == checkListHeaderNewDTO.CheckListTemplateHeaderId)
                                                    .OrderBy(o => o.RowIndex)
                                                    .ToListAsync();
                foreach (var item in checkListTemplateRows)
                {
                    CheckListRow checkListRow = new CheckListRow()
                    {
                        Answer = "",
                        CheckListHeaderId = checkListHeader.Id,
                        CheckListTemplateRowId = item.Id,
                        GuidNumber = Guid.NewGuid(),
                        IsDeleted = false,
                        PhotoFileName = "",
                    };
                    _dbContext.CheckListRows.Add(checkListRow);
                }

                await _dbContext.SaveChangesAsync();
                await transaction.CommitAsync();

                retVal = _mapper.Map<CheckListHeaderDTO>(checkListHeader);
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                Log.Error(ex.Message);
            }
            return retVal;
        }

        public async Task<CheckListTemplateHeaderDTO> GetCheckListTemplateHeaderAsync(int Id)
        {
            var retVal = new CheckListTemplateHeaderDTO()
            {
                CheckListTemplateRowDTO = new List<CheckListTemplateRowDTO>()
            };

            try
            {
                var res = await _dbContext.CheckListTemplateHeaders
                                       .Where(w => w.Id == Id)
                                       .Include(i => i.CheckListTemplateRows)
                                            .ThenInclude(i => i.CheckPoint)
                                       .Include(i => i.CheckListTemplateRows)
                                            .ThenInclude(i => i.Equipment)
                                       .AsNoTracking()
                                       .FirstOrDefaultAsync();

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

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

            return retVal;
        }
        public async Task<List<CheckListTemplateHeaderDTO>> GetAllCheckListTemplateHeaderAsync()
        {
            var retVal = new List<CheckListTemplateHeaderDTO>();
            try
            {
                var roles = await _dbContext.CheckListTemplateHeaders
                                            .Include(i => i.CheckListTemplateRows)
                                            .AsNoTracking()
                                            .ToListAsync();
                if (roles != null)
                {
                    retVal = _mapper.Map<List<CheckListTemplateHeaderDTO>>(roles);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return retVal;
        }
        public async Task<CheckListTemplateHeaderDTO> UpdateCheckListTemplateHeaderAsync(CheckListTemplateHeaderDTO checkListTemplateHeaderDTO)
        {
            var retVal = new CheckListTemplateHeaderDTO() { CheckListTemplateRowDTO = new List<CheckListTemplateRowDTO>() };
            try
            {
                if (checkListTemplateHeaderDTO.Id == 0)
                {
                    var checkListTemplateHeader = new CheckListTemplateHeader()
                    {
                        Description = checkListTemplateHeaderDTO.Description,
                        ShortName = checkListTemplateHeaderDTO.ShortName,
                        IsDeleted = false,
                        NumberGenerator1Id = checkListTemplateHeaderDTO.NumberGenerator1Id,
                        NumberGenerator2Id = checkListTemplateHeaderDTO.NumberGenerator2Id,

                    };
                    _dbContext.CheckListTemplateHeaders.Add(checkListTemplateHeader);
                    await _dbContext.SaveChangesAsync();
                    retVal = _mapper.Map<CheckListTemplateHeaderDTO>(checkListTemplateHeader);
                }
                else
                {
                    var checkListTemplateHeader = await _dbContext.CheckListTemplateHeaders
                                            .Include(i => i.CheckListTemplateRows)
                                            .Where(w => w.Id == checkListTemplateHeaderDTO.Id)
                                            .FirstOrDefaultAsync();
                    if (checkListTemplateHeader != null)
                    {
                        checkListTemplateHeader.Description = checkListTemplateHeaderDTO.Description;
                        checkListTemplateHeader.ShortName = checkListTemplateHeaderDTO.ShortName;

                        await _dbContext.SaveChangesAsync();
                        retVal = _mapper.Map<CheckListTemplateHeaderDTO>(checkListTemplateHeader);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<CheckListTemplateRowDTO> GetCheckListTemplateRowAsync(int id)
        {
            var retVal = new CheckListTemplateRowDTO();
            try
            {
                var res = await _dbContext.CheckListTemplateRows
                                       .Include(i => i.Equipment)
                                       .Include(i => i.CheckPoint)
                                       .Where(w => w.Id == id)
                                       .AsNoTracking()
                                       .FirstOrDefaultAsync();

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

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

            return retVal;
        }
        public async Task<CheckListTemplateRowDTO> UpdateCheckListTemplateRowAsync(CheckListTemplateRowDTO checkListTemplateRowDTO)
        {
            var retVal = new CheckListTemplateRowDTO() { };
            try
            {
                if (checkListTemplateRowDTO.Id == 0)
                {
                    var checkListTemplateRow = new CheckListTemplateRow()
                    {
                        CheckListTemplateHeaderId = checkListTemplateRowDTO.CheckListTemplateHeaderId,
                        CheckPointId = checkListTemplateRowDTO.CheckPointId,
                        EquipmentId = checkListTemplateRowDTO.EquipmentId,
                        OperationDescription = checkListTemplateRowDTO.OperationDescription,
                        AnswerType = checkListTemplateRowDTO.AnswerType,
                        RowIndex = checkListTemplateRowDTO.RowIndex,

                    };
                    _dbContext.CheckListTemplateRows.Add(checkListTemplateRow);
                    await _dbContext.SaveChangesAsync();
                    retVal = _mapper.Map<CheckListTemplateRowDTO>(checkListTemplateRow);
                }
                else
                {
                    var checkListTemplateRow = await _dbContext.CheckListTemplateRows
                                            .Where(w => w.Id == checkListTemplateRowDTO.Id)
                                            .FirstOrDefaultAsync();
                    if (checkListTemplateRow != null)
                    {
                        checkListTemplateRow.CheckListTemplateHeaderId = checkListTemplateRowDTO.CheckListTemplateHeaderId;
                        checkListTemplateRow.CheckPointId = checkListTemplateRowDTO.CheckPointId;
                        checkListTemplateRow.EquipmentId = checkListTemplateRowDTO.EquipmentId;
                        checkListTemplateRow.OperationDescription = checkListTemplateRowDTO.OperationDescription;
                        checkListTemplateRow.AnswerType = checkListTemplateRowDTO.AnswerType;
                        checkListTemplateRow.RowIndex = checkListTemplateRowDTO.RowIndex;

                        await _dbContext.SaveChangesAsync();
                        retVal = _mapper.Map<CheckListTemplateRowDTO>(checkListTemplateRow);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<CheckListRowDTO> GetCheckListRowAsync(int id)
        {
            var retVal = new CheckListRowDTO();
            try
            {
                var res = await _dbContext.CheckListRows
                                       .Include(i => i.CheckListTemplateRow)
                                       .Where(w => w.Id == id)
                                       .AsNoTracking()
                                       .FirstOrDefaultAsync();

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

            return retVal;
        }
        public async Task<CheckListRowDTO> UpdateCheckListRowAsync(CheckListRowDTO checkListRowDTO)
        {
            var retVal = new CheckListRowDTO() { };
            try
            {
                if (checkListRowDTO.Id == 0)
                {

                }
                else
                {
                    var checkListRow = await _dbContext.CheckListRows
                                            .Where(w => w.Id == checkListRowDTO.Id)
                                            .FirstOrDefaultAsync();
                    if (checkListRow != null)
                    {
                        checkListRow.Answer = checkListRowDTO.Answer;
                        //checkListRow.Photo = checkListRowDTO.Photo;
                        await _dbContext.SaveChangesAsync();
                        retVal = _mapper.Map<CheckListRowDTO>(checkListRow);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }

            return retVal;
        }

        public async Task<byte[]> CreatePDF(int checkListHeaderId)
        {
            try
            {
                var checkListHeader = await this.GetCheckListHeaderAsync(checkListHeaderId);

                string pdfDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Pdf");

                byte[] byteArray = File.ReadAllBytes(Path.Combine(pdfDirectory, "CheckList_Template_V1.docx"));
                SablonGenerator gen = new SablonGenerator(byteArray);

                if (checkListHeader.CheckListRowDTO != null && checkListHeader.CheckListRowDTO.Count > 0)
                {
                    var elements = new List<List<string>>();
                    foreach (var item in checkListHeader.CheckListRowDTO)
                    {
                        if (item.CheckListTemplateRowDTO != null)
                        {
                            var cells = new List<string>
                                {
                                    $"{item.CheckListTemplateRowDTO.RowIndex.ToString()}.",
                                    item.CheckListTemplateRowDTO.OperationDescription,
                                    item.Answer
                                };
                            elements.Add(cells);
                        }
                    }
                    gen.SetTable(elements, "#rowindex");
                }


                byte[] content = gen.CloseAndGetDocument();

                return DokumentumGenerator.DocxToPdfL(content);
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message);
            }
            return new byte[0];
        }
    }
}
