using Elwig.Helpers;
using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Elwig.Models.Dtos.WineLocalityStatisticsData;

namespace Elwig.Models.Dtos {
    class WineLocalityStatisticsData : DataTable<StatisticsRow> {

        private static readonly (string, string, string?, int?)[] FieldNames = [
            ("Branch", "Zwst.", null, 30),
            ("KgNr", "KgNr.", null, 15),
            ("Name", "Katastralgemeinde", null, 50),
            ("Members", "Mitgl.", "#", 15),
            ("Deliveries", "Lfrg.", "#", 15),
            ("Parts", "Teill.", "#", 15),
            ("Weight", "Menge", "kg", 20),
            ("Gradation", "Gradation", "°Oe|°KMW", 30),
        ];

        public record struct StatisticsRow(
            string Branch,
            int? KgNr,
            string? Name,
            int Members,
            int Deliveries,
            int Parts,
            int Weight,
            (double Oe, double Kmw) Gradation
        );

        public WineLocalityStatisticsData(IEnumerable<StatisticsRow> rows, List<string> filterNames) :
            base("Lieferstatistik pro Ort", "Lieferstatistik pro Ort", string.Join(" / ", filterNames), rows, FieldNames) {
        }

        public static async Task<WineLocalityStatisticsData> FromQuery(IQueryable<DeliveryPart> query, List<string> filterNames) {
            return new((await query
                .GroupBy(p => new {
                    Branch = p.Delivery.Branch.Name,
                    p.Kg!.KgNr,
                    Kg = p.Kg!.AtKg.Name,
                }, (k, g) => new {
                    k.Branch,
                    KgNr = (int?)k.KgNr,
                    Kg = (string?)k.Kg,
                    Members = g.Select(p => p.Delivery.Member).Distinct().Count(),
                    Deliveries = g.Select(p => p.Delivery).Distinct().Count(),
                    Parts = g.Count(),
                    Weight = g.Sum(p => p.Weight),
                    Kmw = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
                })
                .OrderByDescending(g => g.Weight)
                .ThenBy(g => g.KgNr)
                .ToListAsync()).Select(g => new StatisticsRow(g.Branch, g.KgNr, g.Kg, g.Members, g.Deliveries, g.Parts, g.Weight, (Utils.KmwToOe(g.Kmw), Math.Round(g.Kmw, 1)))), filterNames);
        }
    }
}
