using HotelBusinessLogic.OfficePackage;
using HotelBusinessLogic.OfficePackage.HelpersModels;
using HotelContracts.BindingModels;
using HotelContracts.BusinessLogicsContracts;
using HotelContracts.SearchModels;
using HotelContracts.StoragesContracts;
using HotelContracts.ViewModels;
using HotelDataModels.Models;

namespace HotelBusinessLogic.BusinessLogics;

public class ReportLogic : IReportLogic
{
    private readonly IGuestStorage _guestStorage;
    private readonly ICleaningStorage _cleaningStorage;
    private readonly ICleaningInstrumentsStorage _cleaningInstruments;
    private readonly IRoomStorage _roomStorage;
    private readonly IReservationStorage _reservationStorage;
    
    private readonly AbstractSaveToExcel _saveToExcel;
    private readonly AbstractSaveToWord _saveToWord;
    private readonly AbstractSaveToPdf _saveToPdf;

    public ReportLogic(IGuestStorage guestStorage, 
        ICleaningStorage cleaningStorage, 
        ICleaningInstrumentsStorage cleaningInstruments, 
        IRoomStorage roomStorage, 
        IReservationStorage reservationStorage, 
        AbstractSaveToExcel saveToExcel, 
        AbstractSaveToWord saveToWord, 
        AbstractSaveToPdf saveToPdf)
    {
        _guestStorage = guestStorage;
        _cleaningStorage = cleaningStorage;
        _cleaningInstruments = cleaningInstruments;
        _roomStorage = roomStorage;
        _reservationStorage = reservationStorage;
        _saveToExcel = saveToExcel;
        _saveToWord = saveToWord;
        _saveToPdf = saveToPdf;
    }

    public List<ReportListCleaningModel> GetListCleaning()
    {
        var reservations = _reservationStorage.GetFullList();
        List<ReportListCleaningModel> list = new();

        foreach (var reservation in reservations)
        {
            foreach (var room in reservation.ReservationsRooms.Values)
            {
                var cleaning = _cleaningStorage.GetElement(new CleaningSearchModel { RoomId = room.Id });
                if (cleaning == null)
                    break;
                var dict = new Dictionary<int, CleaningInstrumentsViewModel>();
                foreach (var item in cleaning.CleaningInstruments)
                {
                    var view = new CleaningInstrumentsViewModel()
                    {
                        Id = item.Value.Id,
                        Type = item.Value.Type
                    };
                    dict.Add(item.Key, view);
                }

                list.Add(new ReportListCleaningModel
                {
                    RoomNumber = room.Id,
                    StartDate = reservation.StartDate,
                    CleaningInstruments = dict
                });
            }
        }

        return list;
    }

    public List<ReportGuestViewModel> GetGuests(ReportBindingModel model)
    {
        var list = new List<ReportGuestViewModel>();
        var guests = _guestStorage.GetFullList();
        foreach (var guest in guests)
        {
            var reservations = _reservationStorage.GetFilteredList(new ReservationSearchModel
            {
                GuestId = guest.Id
            });

            foreach (var reservation in reservations)
            {
                foreach (var room in reservation.ReservationsRooms.Values)
                {
                    var cleaning = _cleaningStorage.GetElement(new CleaningSearchModel { RoomId = room.Id });
                    if (cleaning == null)
                        break;
                    var dict = new Dictionary<int, CleaningInstrumentsViewModel>();
                    foreach (var item in cleaning.CleaningInstruments)
                    {
                        var view = new CleaningInstrumentsViewModel()
                        {
                            Id = item.Value.Id,
                            Type = item.Value.Type
                        };
                        dict.Add(item.Key, view);
                    }

                    list.Add(new ReportGuestViewModel()
                    {
                        Name = guest.Name,
                        SecondName = guest.SecondName,
                        LastName = guest.LastName,
                        StartDate = reservation.StartDate,
                        EndDate = reservation.EndDate,
                        CleaningInstruments = dict
                    });
                }
            }
        }

        return list;
    }

    public void SaveListCleaningToWordFile(ReportBindingModel model)
    {
        _saveToWord.CreateDoc(new WordInfo
        {
            FileName = model.FileName,
            Title = "Cleaning list",
            ListCleaningModels = GetListCleaning()
        });
    }

    public void SaveListCleaningToExcelFile(ReportBindingModel model)
    {
        _saveToExcel.CreateReport(new ExcelInfo
        {
            FileName = model.FileName,
            Title = "Cleaning list",
            ListCleaningModels = GetListCleaning()
        });
    }

    public void SaveGuestsToPdfFile(ReportBindingModel model)
    {
        _saveToPdf.CreateDoc(new PdfInfo
        {
            FileName = model.FileName,
            Title = "Guests with sets of cleanings",
            DateFrom = (DateTime)model.From,
            DateTo = (DateTime)model.To
        });
    }
}