using Elwig.Helpers;
using Elwig.Helpers.Export;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace Elwig.Windows {
    public partial class QueryWindow : Window {

        private ICommand? _enterCommand;
        public ICommand EnterCommand => _enterCommand ??= new ActionCommand(async () => {
            await DisplayQuery();
        });

        private ICommand? _saveCommand;
        public ICommand SaveCommand => _saveCommand ??= new ActionCommand(async () => {
            await SaveQuery();
        });


        public QueryWindow() {
            InitializeComponent();
        }

        private async void QueryButton_Click(object sender, RoutedEventArgs evt) {
            await DisplayQuery();
        }

        private async void SaveButton_Click(object sender, RoutedEventArgs evt) {
            await SaveQuery();
        }

        private async Task DisplayQuery() {
            try {
                Mouse.OverrideCursor = Cursors.Wait;
                await DisplayQuery(QueryInput.Text);
                Mouse.OverrideCursor = null;
            } catch (Exception e) {
                Mouse.OverrideCursor = null;
                MessageBox.Show(e.Message, "Fehler beim Ausführen", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private async Task SaveQuery() {
            await SaveQuery(QueryInput.Text);
        }

        private static async Task<(IList<DbColumn>, IEnumerable<object[]>)> ExecuteQuery(string sqlQuery) {
            var rows = new List<object[]>();
            using var cnx = await AppDbContext.ConnectAsync();
            using var cmd = cnx.CreateCommand();
            cmd.CommandText = sqlQuery;
            using var reader = await cmd.ExecuteReaderAsync();
            var header = await reader.GetColumnSchemaAsync();
            while (await reader.ReadAsync()) {
                var values = new object[reader.FieldCount];
                reader.GetValues(values);
                rows.Add(values);
            }
            return (header, rows);
        }

        private async Task DisplayQuery(string sqlQuery) {
            var (header, rows) = await ExecuteQuery(sqlQuery);
            var styleRight = new Style();
            styleRight.Setters.Add(new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Right));

            DataList.Columns.Clear();
            for (int i = 0; i < header.Count; i++) {
                var h = header[i];
                DataList.Columns.Add(new DataGridTextColumn {
                    Header = h.ColumnName.Replace("_", "__"),
                    Binding = new Binding($"[{i}]"),
                    CellStyle = (h.DataTypeName == "INTEGER" || h.DataTypeName == "REAL") ? styleRight : null,
                });
            }
            DataList.ItemsSource = rows;
        }

        private static async Task SaveQuery(string sqlQuery) {
            var d = new SaveFileDialog() {
                FileName = $"Abfrage.csv",
                DefaultExt = "csv",
                Filter = "CSV-Datei (*.csv)|*.csv",
                Title = $"Datenbank Abfrage speichern unter - Elwig"
            };
            if (d.ShowDialog() == true) {
                Mouse.OverrideCursor = Cursors.Wait;
                await Task.Run(async () => {
                    try {
                        var (header, rows) = await ExecuteQuery(sqlQuery);
                        using var csv = new CsvSimple(d.FileName, ';', Utils.UTF8BOM);
                        await csv.ExportAsync(rows.Prepend([.. header.Select(h => h.ColumnName)]));
                    } catch (Exception exc) {
                        MessageBox.Show(exc.Message, "Fehler beim Ausführen", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                });
                Mouse.OverrideCursor = null;
            }
        }
    }
}
