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

namespace Elwig.Windows {
    public partial class BaseDataWindow {

        private Dictionary<string, string?>? _branches = null;
        private Dictionary<Branch, string>? _branchIds = null;
        private ObservableCollection<Branch>? _branchList = null;
        private bool _branchChanged = false;
        private bool _branchUpdate = false;

        private async Task BranchesInitEditing(AppDbContext ctx) {
            _branchList = new(await ctx.Branches
                .OrderBy(b => b.Name)
                .Include(b => b.PostalDest!.AtPlz)
                .ToListAsync());
            _branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId);
            _branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId);
            ControlUtils.RenewItemsSource(BranchList, _branchList);
            BranchList_SelectionChanged(null, null);
        }

        private async Task BranchesFinishEditing(AppDbContext ctx) {
            ControlUtils.RenewItemsSource(BranchList, await ctx.Branches
                .OrderBy(b => b.Name)
                .Include(b => b.PostalDest!.AtPlz)
                .ToListAsync());
            _branchList = null;
            _branches = null;
            _branchIds = null;
            _branchChanged = false;

            BranchAddButton.IsEnabled = false;
            BranchDeleteButton.IsEnabled = false;
        }

        private async Task BranchesSave(AppDbContext ctx) {
            if (!_branchChanged || _branchList == null || _branches == null || _branchIds == null)
                return;

            foreach (var (zwstid, _) in _branches.Where(b => b.Value == null)) {
                ctx.Remove(ctx.Branches.Find(zwstid)!);
            }
            foreach (var (branch, old) in _branchIds) {
                branch.ZwstId = old;
            }
            foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) {
                ctx.Update(ctx.Branches.Find(old)!);
            }
            await ctx.SaveChangesAsync();

            foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) {
                await ctx.Database.ExecuteSqlAsync($"UPDATE branch SET zwstid = {zwstid} WHERE zwstid = {old}");
            }
            await ctx.SaveChangesAsync();

            foreach (var branch in _branchList.Where(b => !_branchIds.ContainsKey(b))) {
                if (branch.ZwstId == null) continue;
                ctx.Add(branch);
            }
            await ctx.SaveChangesAsync();
        }

        private void BranchList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
            UpdateButtons();
            _branchUpdate = true;
            if (BranchList.SelectedItem is not Branch branch) {
                BranchIdInput.Text = "";
                BranchNameInput.Text = "";
                BranchPlzInput.Text = "";
                BranchAddressInput.Text = "";
                BranchPhoneNrInput.Text = "";
                BranchFaxNrInput.Text = "";
                BranchMobileNrInput.Text = "";
            } else {
                BranchIdInput.Text = branch.ZwstId;
                BranchNameInput.Text = branch.Name;
                BranchPlzInput.Text = branch.PostalDest?.AtPlz?.Plz.ToString() ?? "";
                ControlUtils.SelectItem(BranchOrtInput, branch.PostalDest?.AtPlz);
                BranchAddressInput.Text = branch.Address;
                BranchPhoneNrInput.Text = branch.PhoneNr;
                BranchFaxNrInput.Text = branch.FaxNr;
                BranchMobileNrInput.Text = branch.MobileNr;
            }
            _branchUpdate = false;
        }

        private void BranchAddButton_Click(object sender, RoutedEventArgs evt) {
            if (_branchList == null) return;
            _branchChanged = true;
            var item = new Branch { ZwstId = "", Name = "" };
            _branchList.Add(item);
            BranchList.SelectedItem = item;
            UpdateButtons();
        }

        private void BranchDeleteButton_Click(object sender, RoutedEventArgs evt) {
            if (_branchList == null || _branches == null) return;
            _branchChanged = true;
            var idx = BranchList.SelectedIndex;
            var item = _branchList[idx];
            _branches[item.ZwstId] = null;
            _branchList.RemoveAt(idx);
            BranchList.SelectedIndex = idx < _branchList.Count ? idx : idx - 1;
            UpdateButtons();
        }

        private void Branch_Changed(object? sender, RoutedEventArgs? evt) {
            if (_branchUpdate || (!IsEditing && !IsCreating) || BranchList.SelectedItem is not Branch branch || _branches == null || _branchIds == null) return;
            _branchChanged = _branchChanged ||
                BranchIdInput.Text != branch.ZwstId ||
                BranchNameInput.Text != branch.Name ||
                BranchPlzInput.Text != (branch.PostalDest?.AtPlz?.Plz.ToString() ?? "") ||
                (BranchOrtInput.SelectedItem as AT_PlzDest)?.Okz != branch.PostalDest?.AtPlz?.Okz ||
                BranchAddressInput.Text != branch.Address ||
                BranchPhoneNrInput.Text != (branch.PhoneNr ?? "") ||
                BranchFaxNrInput.Text != (branch.FaxNr ?? "") ||
                BranchMobileNrInput.Text != (branch.MobileNr ?? "");

            var old = _branchIds.GetValueOrDefault(branch);
            var id = BranchIdInput.Text;
            if (old != null) _branches[old] = id;
            branch.ZwstId = id;
            branch.Name = BranchNameInput.Text;
            branch.CountryNum = 40;
            branch.PostalDestId = (BranchOrtInput.SelectedItem as AT_PlzDest)?.Id;
            branch.Address = BranchAddressInput.Text;
            branch.PhoneNr = BranchPhoneNrInput.Text;
            branch.FaxNr = BranchFaxNrInput.Text;
            branch.MobileNr = BranchMobileNrInput.Text;
            if (branch.PhoneNr.Length == 0) branch.PhoneNr = null;
            if (branch.FaxNr.Length == 0) branch.FaxNr = null;
            if (branch.MobileNr.Length == 0) branch.MobileNr = null;

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

        private void BranchPlzInput_TextChanged(object sender, TextChangedEventArgs evt) {
            PlzInput_TextChanged(sender, evt);
            Branch_Changed(sender, evt);
        }

        private void BranchPhoneNr_TextChanged(object sender, TextChangedEventArgs evt) {
            PhoneNrInput_TextChanged(sender, evt);
            Branch_Changed(sender, evt);
        }
    }
}
