using Elwig.Helpers;
using Elwig.Models.Entities;
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 async Task WineCultivationsInitEditing(AppDbContext ctx) {
            _cultList = new(await ctx.WineCultivations
                .OrderBy(c => c.Name)
                .ToListAsync());
            _cults = _cultList.ToDictionary(c => c.CultId, c => (string?)c.CultId);
            _cultIds = _cultList.ToDictionary(c => c, c => c.CultId);
            ControlUtils.RenewItemsSource(WineCultivationList, _cultList);
            WineCultivationList_SelectionChanged(null, null);
        }

        private async Task WineCultivationsFinishEditing(AppDbContext ctx) {
            ControlUtils.RenewItemsSource(WineCultivationList, await ctx.WineCultivations
                .OrderBy(c => c.Name)
                .ToListAsync());
            _cultList = null;
            _cults = null;
            _cultIds = null;
            _cultChanged = false;

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

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

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

            foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) {
                await ctx.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}");
                await ctx.Database.ExecuteSqlRawAsync($"UPDATE payment_variant SET data = REPLACE(data, '-{old}\"', '-{cultid}\"')");
            }
            await ctx.SaveChangesAsync();

            foreach (var cult in _cultList.Where(c => !_cultIds.ContainsKey(c))) {
                if (cult.CultId == null) continue;
                ctx.Add(cult);
            }
            await ctx.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 = new WineCult { CultId = "", Name = "" };
            _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);
        }
    }
}