using Elwig.Helpers;
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows;

namespace Elwig.Windows {
    public partial class BaseDataWindow {

        private Dictionary<string, string?>? _cults = null;
        private Dictionary<WineCult, string>? _cultIds = null;
        private ObservableCollection<WineCult>? _cultList = null;
        private bool _cultChanged = false;
        private bool _cultUpdate = false;

        private void WineCultivationsInitEditing() {
            _cultList = new(Context.WineCultivations.OrderBy(c => c.Name).ToList());
            _cults = _cultList.ToDictionary(c => c.CultId, c => (string?)c.CultId);
            _cultIds = _cultList.ToDictionary(c => c, c => c.CultId);
            ControlUtils.RenewItemsSource(WineCultivationList, _cultList, c => (c as WineCult)?.CultId);
        }

        private void WineCultivationsFinishEditing() {
            ControlUtils.RenewItemsSource(WineCultivationList, Context.WineCultivations.OrderBy(c => c.Name).ToList(), c => (c as WineCult)?.CultId);
            _cultList = null;
            _cults = null;
            _cultIds = null;
            _cultChanged = false;

            WineCultivationAddButton.IsEnabled = false;
            WineCultivationDeleteButton.IsEnabled = false;
        }

        private async Task WineCultivationsSave() {
            if (!_cultChanged || _cultList == null || _cults == null || _cultIds == null)
                return;

            foreach (var (cultid, _) in _cults.Where(c => c.Value == null)) {
                Context.Remove(Context.WineCultivations.Find(cultid));
            }
            foreach (var (cult, old) in _cultIds) {
                cult.CultId = old;
            }
            foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) {
                Context.Update(Context.WineCultivations.Find(old));
            }
            await Context.SaveChangesAsync();

            foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) {
                await Context.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}");
            }
            await Context.SaveChangesAsync();

            foreach (var cult in _cultList.Where(c => !_cultIds.ContainsKey(c))) {
                if (cult.CultId == null) continue;
                await Context.AddAsync(cult);
            }
            await Context.SaveChangesAsync();
        }

        private void WineCultivationList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
            UpdateButtons();
            _cultUpdate = true;
            if (WineCultivationList.SelectedItem is not WineCult cult) {
                WineCultivationIdInput.Text = "";
                WineCultivationNameInput.Text = "";
                WineCultivationDescriptionInput.Text = "";
            } else {
                WineCultivationIdInput.Text = cult.CultId;
                WineCultivationNameInput.Text = cult.Name;
                WineCultivationDescriptionInput.Text = cult.Description;
            }
            _cultUpdate = false;
        }

        private void WineCultivationAddButton_Click(object sender, RoutedEventArgs evt) {
            if (_cultList == null) return;
            _cultChanged = true;
            var item = Context.CreateProxy<WineCult>();
            _cultList.Add(item);
            WineCultivationList.SelectedItem = item;
            UpdateButtons();
        }

        private void WineCultivationDeleteButton_Click(object sender, RoutedEventArgs evt) {
            if (_cultList == null || _cults == null) return;
            _cultChanged = true;
            var idx = WineCultivationList.SelectedIndex;
            var item = _cultList[idx];
            _cults[item.CultId] = null;
            _cultList.RemoveAt(idx);
            WineCultivationList.SelectedIndex = idx < _cultList.Count ? idx : idx - 1;
            UpdateButtons();
        }

        private void WineCultivation_Changed(object? sender, RoutedEventArgs? evt) {
            if (_cultUpdate || (!IsEditing && !IsCreating) || WineCultivationList.SelectedItem is not WineCult cult || _cults == null || _cultIds == null) return;
            _cultChanged = _cultChanged ||
                WineCultivationIdInput.Text != cult.CultId ||
                WineCultivationNameInput.Text != cult.Name ||
                WineCultivationDescriptionInput.Text != (cult.Description ?? "");

            var old = _cultIds.GetValueOrDefault(cult);
            var id = WineCultivationIdInput.Text ?? "";
            if (old != null) _cults[old] = id;
            cult.CultId = id;
            cult.Name = WineCultivationNameInput.Text ?? "";
            cult.Description = WineCultivationDescriptionInput.Text ?? "";
            if (cult.Description.Length == 0) cult.Description = null;

            CollectionViewSource.GetDefaultView(_cultList).Refresh();
            UpdateButtons();
        }

        private void WineCultivationIdInput_TextChanged(object sender, TextChangedEventArgs evt) {
            UpperCaseInput_TextChanged(sender, evt);
            WineCultivation_Changed(sender, evt);
        }
    }
}