using Elwig.Dialogs;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Microsoft.Win32;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace Elwig.Windows {
    public partial class SeasonFinishWindow : ContextWindow {
        public SeasonFinishWindow() {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs evt) {
            SeasonInput.Value = Utils.CurrentLastSeason;
        }

        protected override async Task OnRenewContext() {
            SeasonInput_ValueChanged(null, null);
        }

        private async void SeasonInput_ValueChanged(object? sender, RoutedEventArgs? evt) {
            var s0 = await Context.Seasons.FindAsync(SeasonInput.Value);
            var s1 = await Context.Seasons.FindAsync(SeasonInput.Value + 1);
            var valid = (s0 != null);
            var last = (s1 == null);
            CalculateBinsButton.IsEnabled = valid && last;
            DeliveryConfirmationButton.IsEnabled = valid;
            OverUnderDeliveryButton.IsEnabled = valid;
        }

        private async void CalculateBinsButton_Click(object sender, RoutedEventArgs evt) {
            if (SeasonInput.Value is not int year)
                return;
            CalculateBinsButton.IsEnabled = false;
            Mouse.OverrideCursor = Cursors.AppStarting;
            var b = new Billing(year);
            await b.FinishSeason();
            await b.CalculateBins(
                AllowAttrIntoLowerBinsInput.IsChecked ?? false,
                AvoidUnderDeliveriesInput.IsChecked ?? false,
                HonorGebundenInput.IsChecked ?? false);
            Mouse.OverrideCursor = null;
            CalculateBinsButton.IsEnabled = true;
        }

        private void DeliveryConfirmationButton_Click(object sender, RoutedEventArgs evt) {
            if (SeasonInput.Value is not int year)
                return;
            var w = new DeliveryConfirmationsWindow(year);
            w.Show();
        }

        private async void OverUnderDeliveryButton_Click(object sender, RoutedEventArgs evt) {
            if (SeasonInput.Value is not int year)
                return;
            var d = new SaveFileDialog() {
                FileName = $"Über-Unterlieferungen-{year}.csv",
                DefaultExt = "csv",
                Filter = "CSV-Datei (*.csv)|*.csv",
                Title = $"Über-/Unterlieferungen {year} speichern unter - Elwig"
            };
            if (d.ShowDialog() == false)
                return;

            Mouse.OverrideCursor = Cursors.AppStarting;

            try {
                using var file = new StreamWriter(d.FileName, false, Encoding.Latin1);
                using var cnx = await AppDbContext.ConnectAsync();
                await file.WriteLineAsync($"Auswertungen {year};;;;;;;;;;;");

                await file.WriteLineAsync($";;;;;;;;;;;");
                await file.WriteLineAsync($"Über-/Unterlieferungen lt. gez. GA;;;;;;;;;;;");
                await file.WriteLineAsync($"MgNr;Name;Vorname;Adresse;PLZ;Ort;GA;Lieferpflicht;Lieferrecht;Geliefert;Über-/Unterliefert;Prozent");
                using (var cmd = cnx.CreateCommand()) {
                    cmd.CommandText = $"""
                    SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name, m.address, m.business_shares,
                           m.business_shares * (SELECT value FROM client_parameter WHERE param = 'DELIVERY_OBLIGATION') AS min_kg,
                           m.business_shares * (SELECT value FROM client_parameter WHERE param = 'DELIVERY_RIGHT') AS max_kg,
                           COALESCE(SUM(d.weight), 0) AS sum
                    FROM member m
                        LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest
                        LEFT JOIN AT_ort o ON o.okz = p.okz
                        LEFT JOIN v_delivery d ON d.mgnr = m.mgnr AND d.year = {year}
                    WHERE m.active = 1
                    GROUP BY d.year, m.mgnr
                    ORDER BY sum = 0 DESC, 100.0 * sum / max_kg, m.mgnr;
                    """;
                    using var reader = await cmd.ExecuteReaderAsync();
                    while (await reader.ReadAsync()) {
                        var mgnr = reader.GetInt32(0);
                        var familyName = reader.GetString(1);
                        var givenName = reader.GetString(2);
                        var plz = reader.GetInt32(3);
                        var ort = reader.GetString(4);
                        var addr = reader.GetString(5);
                        var ga = reader.GetInt32(6);
                        var minKg = reader.GetInt32(7);
                        var maxKg = reader.GetInt32(8);
                        var sum = reader.GetInt32(9);
                        var s1 = sum < minKg ? $"{sum - minKg}" : sum > maxKg ? $"{sum - maxKg}" : "";
                        var s2 = sum < minKg ? $"{sum * 100.0 / minKg - 100.0:0.0}" : sum > maxKg ? $"{sum * 100.0 / maxKg - 100:0.0}" : "";
                        await file.WriteLineAsync($"{mgnr};{familyName};{givenName};{addr};{plz};{ort};{ga};{minKg};{maxKg};{sum};{s1};{s2}");
                    }
                }

                await file.WriteLineAsync($";;;;;;;;;;;");
                await file.WriteLineAsync($"Unterlieferungen lt. Flächenbindungen;;;;;;;;;;;");
                await file.WriteLineAsync($"MgNr;Name;Vorname;Adresse;PLZ;Ort;Vertrag;Lieferpflicht;Lieferrecht;Geliefert;Unterliefert;Prozent");
                using (var cmd = cnx.CreateCommand()) {
                    cmd.CommandText = $"""
                    SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name, m.address,
                           c.bin, c.min_kg, c.max_kg, b.weight
                    FROM member m
                        LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest
                        LEFT JOIN AT_ort o ON o.okz = p.okz
                        JOIN v_area_commitment_bin c ON c.mgnr = m.mgnr AND c.year = {year}
                        LEFT JOIN v_payment_bin b ON (b.mgnr, b.bin) = (m.mgnr, c.bin) AND b.year = {year}
                    WHERE m.active = 1 AND b.weight < c.min_kg
                    ORDER BY m.mgnr, c.bin
                    """;
                    using var reader = await cmd.ExecuteReaderAsync();
                    while (await reader.ReadAsync()) {
                        var mgnr = reader.GetInt32(0);
                        var familyName = reader.GetString(1);
                        var givenName = reader.GetString(2);
                        var plz = reader.GetInt32(3);
                        var ort = reader.GetString(4);
                        var addr = reader.GetString(5);
                        var id = reader.GetString(6);
                        var minKg = reader.GetInt32(7);
                        var maxKg = reader.GetInt32(8);
                        var sum = reader.GetInt32(9);
                        await file.WriteLineAsync($"{mgnr};{familyName};{givenName};{addr};{plz};{ort};{id};{minKg};{maxKg};{sum};{sum - minKg};{sum * 100.0 / minKg - 100.0:0.0}");
                    }
                }

            } catch (Exception exc) {
                MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
            }

            Mouse.OverrideCursor = null;
        }

        private void PaymentButton_Click(object sender, RoutedEventArgs evt) {
            var w = new ChartWindow();
            w.Show();
        }
    }
}