using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Elwig.Models.Dtos {
    public class MemberDeliveryPerVarietyData : DataTable<MemberDeliveryPerVarietyRow> {

        private static readonly (string, string, string?, int?)[] FieldNames = [
            ("MgNr", "MgNr.", null, 12),
            ("Name1", "Name", null, 40),
            ("Name2", "Vorname", null, 40),
            ("Address", "Adresse", null, 60),
            ("Plz", "PLZ", null, 10),
            ("Locality", "Ort", null, 60),
            ("SortIds", "Sorte", null, 12),
            ("AttrIds", "Attribut", null, 16),
            ("CultIds", "Bewirt.", null, 16),
            ("Weights", "Geliefert", "kg", 22),
        ];

        public MemberDeliveryPerVarietyData(IEnumerable<MemberDeliveryPerVarietyRow> rows, List<string> filterNames) :
            base("Liefermengen pro Sorte", "Liefermengen pro Mitglied, Sorte, Attribut und Bewirtschaftungsart", string.Join(" / ", filterNames), rows, FieldNames) {
        }

        public static async Task<MemberDeliveryPerVarietyData> FromQuery(IQueryable<DeliveryPart> query, List<string> filterNames) {
            return new((await query
                .GroupBy(p => new {
                    p.Delivery.MgNr,
                    p.Delivery.Member.Name,
                    p.Delivery.Member.GivenName,
                    p.Delivery.Member.Address,
                    p.Delivery.Member.PostalDest.AtPlz!.Plz,
                    Ort = p.Delivery.Member.PostalDest.AtPlz!.Ort.Name,
                    p.SortId,
                    p.AttrId,
                    p.CultId,
                })
                .Select(g => new {
                    g.Key,
                    Weight = g.Sum(p => p.Weight),
                })
                .ToListAsync()).GroupBy(g => new {
                    g.Key.MgNr,
                    g.Key.Name,
                    g.Key.GivenName,
                    g.Key.Address,
                    g.Key.Plz,
                    g.Key.Ort,
                }).Select(g => new MemberDeliveryPerVarietyRow {
                    MgNr = g.Key.MgNr,
                    Name1 = g.Key.Name,
                    Name2 = g.Key.GivenName,
                    Address = g.Key.Address,
                    Plz = g.Key.Plz,
                    Locality = g.Key.Ort,
                    SortIds = [.. g.Select(d => d.Key.SortId)],
                    AttrIds = [.. g.Select(d => d.Key.AttrId)],
                    CultIds = [.. g.Select(d => d.Key.CultId)],
                    Weights = [.. g.Select(d => d.Weight)],
                }), filterNames);
        }
    }

    public class MemberDeliveryPerVarietyRow {
        public required int MgNr;
        public required string Name1;
        public required string? Name2;
        public required string Address;
        public required int Plz;
        public required string Locality;
        public required string[] SortIds;
        public required string?[] AttrIds;
        public required string?[] CultIds;
        public required int[] Weights;
    }
}
