using Avalonia.Controls;
using MsBox.Avalonia.Enums;
using MsBox.Avalonia;
using ReactiveUI;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TravelAroundRussia.Models;
using TravelAroundRussia.Views;
using System.Diagnostics;
using System;

namespace TravelAroundRussia.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        List<Hotel> hotelSelected = new List<Hotel>();//коллекция выбранных отелей [для удаления]
        UserControl uc = new MainTourPage();//главный контроллер, который показывает содержимое страницы
        MainTourPageViewModel mainTourPage = new MainTourPageViewModel();//объект модели взаимодействия со страницей Главная туров
        MainHotelPageViewModel mainHotelPage = new MainHotelPageViewModel();//объект модели взаимодействия со страницей Главная отелей
        EditHotelPageViewModel editHotelPage = new EditHotelPageViewModel();//объект модели взаимодействия со страницей Редактирование отеля
        public static UpKotkovaContext baseConnection = new UpKotkovaContext(); //подключение к базе данных
        /// <summary>
        /// Свойство Содержимого страницы, отрисовывается заново при изменении
        /// </summary>
        public UserControl UC { get => uc; set => this.RaiseAndSetIfChanged(ref uc, value); }
        /// <summary>
        /// Свойство Главная туров для взаимодействия со страницей
        /// </summary>
        public MainTourPageViewModel MainTourPage { get => mainTourPage; set => mainTourPage = value; }
        /// <summary>
        /// Свойство Главная отелей для взаимодействия со страницей
        /// </summary>
        public MainHotelPageViewModel MainHotelPage { get => mainHotelPage; set => mainHotelPage = value; }
        /// <summary>
        /// Свойство Выбранные отели [на странице Главная отелей]
        /// </summary>
        public List<Hotel> HotelSelected { get => hotelSelected; set => hotelSelected = value; }
        /// <summary>
        /// Свойство [Добавление/Редактирование] отеля для взаимодействия со страницей
        /// </summary>
        public EditHotelPageViewModel EditHotelPage { get => editHotelPage; set => editHotelPage = value; }
        /// <summary>
        /// Метод для перехода от страницы туров, к странице отелей
        /// </summary>
        public void TourToHotel()
        {
            MainHotelPage = new MainHotelPageViewModel();
            UC = new MainHotelPage();
        }
        /// <summary>
        /// Метод для перехода от страницы отелей, к странице туров
        /// </summary>
        public void HotelToTour()
        {
            MainTourPage = new MainTourPageViewModel();
            UC = new MainTourPage();
        }
        /// <summary>
        /// Метод для перехода от страницы добавления/редактирования, к странице отелей
        /// </summary>
        public async void EditToHotel()
        {
            ButtonResult buttonResult = await MessageBoxManager.GetMessageBoxStandard("Подтверждение выхода",
                    "Вы действительно хотите выйти? Введенные или измененные вами данные не сохраняться",
                    ButtonEnum.YesNo).ShowAsync();
            switch (buttonResult)
            {
                case ButtonResult.Yes:
                    {
                        MainHotelPage = new MainHotelPageViewModel();
                        UC = new MainHotelPage();
                        break;
                    }
                case ButtonResult.No:
                    {
                        break;
                    }
            }

        }
        /// <summary>
        /// Метод для перехода от страницы отелей, к странице добавления отеля
        /// </summary>
        public void editHotel()
        {
            EditHotelPage = new EditHotelPageViewModel();
            UC = new EditHotelPage();
        }
        /// <summary>
        /// Метод для перехода от страницы отелей, к странице редактирования отеля
        /// </summary>
        /// <param name="id">Id отеля</param>
        public void editHotelId(int id)
        {
            EditHotelPage = new EditHotelPageViewModel(id);
            UC = new EditHotelPage();
        }
        /// <summary>
        /// Метод добавления/редактирования отеля
        /// </summary>
        public async void AddHotel()
        {
            string mess = "";//сообщение об ошибках в форме
            //проверка имени
            //проверяем если значение пустое добавляем текст об ошибке
            if (string.IsNullOrWhiteSpace(EditHotelPage.Hotel.Name))
                mess += "\t - Имя указано некорректно\n";
            //проверка описания
            //проверяем если значение пустое добавляем текст об ошибке
            if (string.IsNullOrWhiteSpace(EditHotelPage.Hotel.Description))
                mess += "\t - Описание указано некорректно\n";
            //проверка кода страны
            //проверяем если значение пустое добавляем текст об ошибке
            if (EditHotelPage.Hotel.CountryCode == null)
                mess += "\t - Код страны указан некорректно\n";
            //проверка количества звезд
            //изменяем количетво звезд с помощью локальной переменной
            EditHotelPage.Hotel.CountOfStars = int.Parse(EditHotelPage.Star);
            //если количество звезд меньше 0 или больше 5, добавляем текст об ошибке
            if (EditHotelPage.Hotel.CountOfStars < 0 || EditHotelPage.Hotel.CountOfStars > 5)
                mess += "\t- Количество звезд указано неправильно - значение должно быть от 0 до 5\n";
            //проверка на корректность заполнения формы
            //если длина сообщения больше 0 выводим текст ошибки, добавление/редактирование не происходит
            if (mess.Length > 0)
                await MessageBoxManager.GetMessageBoxStandard("Некорректное заполнение данных", mess, ButtonEnum.Ok).ShowAsync();
            else//если все успешно
            {
                //поиск туров в стране с эти отелем
                List<Tour> tourInCountry = baseConnection.Tours.Where(tb => tb.CountryCode == EditHotelPage.Hotel.CountryCode).ToList();
                //если количество туров на данный момент нет, выводим информацию в сообщение
                if (tourInCountry.Count == 0)
                    mess += "\n\t- На данный момент в данную страну нет туров\n";
                try
                {
                    //проверяем что именно мы делаем и добавляем/редактируем
                    if (EditHotelPage.Edit)//в случае редактирования - обновляем
                        baseConnection.Update(EditHotelPage.Hotel);
                    else //в случае добавления - добавляем
                        baseConnection.Add(EditHotelPage.Hotel);
                    //сохраняем изменения
                    baseConnection.SaveChanges();
                    //проверяем нужно ли добавить туры к этому отелю
                    if (EditHotelPage.TourCheck)
                    {
                        //удаляем записи если они были
                        baseConnection.HotelOfTours.RemoveRange(baseConnection.HotelOfTours.Where(tb => tb.HotelId == EditHotelPage.Hotel.Id).ToList());
                        //добавляем новые записи для каждого тура в этой стране
                        foreach (Tour tour in tourInCountry)
                        {
                            HotelOfTour ht = new HotelOfTour() { Id = 0, HotelId = EditHotelPage.Hotel.Id, TourId = tour.Id };
                            baseConnection.HotelOfTours.Add(ht);
                        }
                        baseConnection.SaveChanges();//сохраняем изменения
                        //выводим сообщение об успешности операции
                        await MessageBoxManager.GetMessageBoxStandard("Запись успешно сохранена", "Записи были добавлены в таблицу", ButtonEnum.Ok).ShowAsync();
                    }
                    else//если удалять не нужно
                    {
                        //удаляем записи о турах если отель поменял свою геопозицию [а вдруг]
                        baseConnection.HotelOfTours.RemoveRange(baseConnection.HotelOfTours
                            .Where(tb => tb.HotelId == EditHotelPage.Hotel.Id && tb.Hotel.CountryCode != EditHotelPage.Hotel.CountryCode).ToList());
                        baseConnection.SaveChanges();//сохраняем изменения
                    }
                    //перезагружаем страничку с отелями
                    MainHotelPage = new MainHotelPageViewModel();
                    UC = new MainHotelPage();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    //в случае неудач выводим сообщение о том что не вышло
                    await MessageBoxManager.GetMessageBoxStandard("Ошибка сохранения", "Во время созранения данных возникла ошибка", ButtonEnum.Ok).ShowAsync();
                }
            }

        }

        public async void DeleteHotel()
        {
            //проверяем выбраны ли отели для удаления
            //если не выбраны сообщаем пользователю что надо выбрать
            if (HotelSelected.Count > 0)
            {
                string titel = "";//заголовок сообщения
                string mess = "";//сообщение об удалении
                try
                {
                    List<Hotel> deleteHotel = new List<Hotel>();
                    List<Hotel> erDeleteHotel = new List<Hotel>();
                    //цикл для каждого выбранного отеля
                    foreach (Hotel hotel in hotelSelected)
                    {
                        //выбираем туры в котором есть текущий отель
                        //при условии что туры актуальны
                        List<HotelOfTour> list = baseConnection.HotelOfTours.Where(tb => tb.HotelId == hotel.Id && tb.Tour.IsActual == 1).ToList();
                        //если количество туров = 0, то добавляем в лист для удаления
                        if (list.Count == 0)
                        {
                            deleteHotel.Add(hotel);
                        }
                        else//иначе добавляем в лист без удаления и добавляем имя отеля в текст сообщения
                        {
                            mess += "\t- " + hotel.Name + "\n";
                            erDeleteHotel.Add(hotel);
                        }
                    }

                    ButtonResult buttonResult = await MessageBoxManager.GetMessageBoxStandard("Подтверждение удаления",
                        "Вы действительно хотите удалить выбранные отели? Восстановить их будет невозможно",
                        ButtonEnum.YesNo).ShowAsync();
                    switch (buttonResult)
                    {
                        case ButtonResult.Yes:
                            {
                                baseConnection.Hotels.RemoveRange(deleteHotel);//удаляем отели
                                baseConnection.SaveChanges();//сохраняем изменения

                                if (mess == "")//проверяем есть ли неудаленные отели и изменяем данные
                                {
                                    titel = "Успешное удаление отелей";
                                    mess = "Все выбранные вами отели успешно удалены";
                                }
                                else
                                {
                                    titel = "Частичное удаление отелей";
                                    mess = "Мы не можем удалить нижеперечисленные отели, так как они курируются актуальными турами\n\n" + mess;
                                }
                                //выодим сообщение
                                await MessageBoxManager.GetMessageBoxStandard(titel, mess, ButtonEnum.Ok).ShowAsync();
                                //обновляем данные
                                MainHotelPage = new MainHotelPageViewModel();
                                UC = new MainHotelPage();
                                break;
                            }
                        case ButtonResult.No:
                            {
                                break;
                            }
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    //выодим сообщение об ошибке
                    await MessageBoxManager.GetMessageBoxStandard("Ошибка", "При удалении возникла ошибка", ButtonEnum.Ok, Icon.Error).ShowAsync();
                }
            }
            else
            {
                await MessageBoxManager.GetMessageBoxStandard("Ошибка", "Для удаления отеля нужно выбрать хотя бы 1 отель", ButtonEnum.Ok, Icon.Error).ShowAsync();
            }

        }
    }
}