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

namespace Elwig.Models.Dtos {
    public class DeliveryJournalData : DataTable<DeliveryJournalRow> {

        private static readonly (string, string, string?, int?)[] FieldNames = [
            ("LsNr", "LsNr.", null, 30),
            ("Pos", "Pos.", null, 10),
            ("Date", "Datum", null, 20),
            ("Time", "Zeit", null, 20),
            ("DeliveryBranch", "Zweigstelle", null, 30),
            ("MgNr", "MgNr.", null, 12),
            ("Name1", "Name", null, 40),
            ("Name2", "Vorname", null, 40),
            ("MemberBranch", "Stamm-Zwst.", null, 30),
            ("SortId", "Sorte", null, 10),
            ("AttrId", "Attr.", null, 15),
            ("CultId", "Bewirt.", null, 15),
            ("QualId", "Qualität", null, 15),
            ("Gradation", "Gradation", "°Oe|°KMW", 40),
            ("Weight", "Menge", "kg", 20),
            ("IsNetWeight", "Gerebelt", null, 20),
            ("HkId", "Herkunft", null, 20),
            ("Modifiers", "Zu-/Abschläge", null, 40),
            ("Comment", "Anmerkung", null, 60),
        ];

        public DeliveryJournalData(IEnumerable<DeliveryJournalRow> rows, List<string> filterNames) :
            base(DeliveryJournal.Name, DeliveryJournal.Name, string.Join(" / ", filterNames), rows, FieldNames) {
        }

        public static async Task<DeliveryJournalData> FromQuery(IQueryable<DeliveryPart> query, List<string> filterNames) {
            return new((await query
                .Include(p => p.Delivery.Member.Branch)
                .Include(p => p.Delivery.Branch)
                .Include(p => p.PartModifiers).ThenInclude(m => m.Modifier)
                .Include(p => p.Variety)
                .Include(p => p.Attribute)
                .Include(p => p.Cultivation)
                .Include(p => p.Origin)
                .Include(p => p.Quality)
                .AsSplitQuery()
                .ToListAsync()).Select(d => new DeliveryJournalRow(d)), filterNames);
        }
    }

    public class DeliveryJournalRow : IDelivery {
        public string LsNr;
        public int Pos;
        public DateOnly Date;
        public TimeOnly? Time;
        public string DeliveryBranch;
        public int MgNr;
        public string Name1;
        public string? Name2;
        public string AdministrativeName;
        public string? MemberBranch;
        public string SortId;
        public string Variety;
        public string? AttrId;
        public string? Attribute;
        public string? CultId;
        public string? Cultivation;
        public string HkId;
        public string QualId;
        public string Quality;
        public (double Oe, double Kmw) Gradation;
        public double Kmw => Gradation.Kmw;
        public double Oe => Gradation.Oe;
        public int Weight { get; set; }
        public bool IsNetWeight;
        public string? Modifiers;
        public string? Comment;

        public DeliveryJournalRow(DeliveryPart p) {
            var d = p.Delivery;
            var m = d.Member;

            LsNr = d.LsNr;
            Pos = p.DPNr;
            Date = d.Date;
            Time = d.Time;
            DeliveryBranch = d.Branch.Name;
            MgNr = m.MgNr;
            Name1 = m.Name;
            Name2 = m.AdministrativeName2;
            AdministrativeName = m.AdministrativeName;
            MemberBranch = m.Branch?.Name;

            SortId = p.SortId;
            Variety = p.Variety.Name;
            AttrId = p.AttrId;
            Attribute = p.Attribute?.Name;
            CultId = p.CultId;
            Cultivation = p.Cultivation?.Name;
            HkId = p.HkId;
            QualId = p.QualId;
            Quality = p.Quality.Name;
            Gradation = (p.Oe, p.Kmw);
            Weight = p.Weight;
            IsNetWeight = p.IsNetWeight;
            Modifiers = string.Join(" / ", p.Modifiers.Select(m => m.Name).Order());
            Comment = d.Comment == null && p.Comment == null ? null : (d.Comment + (d.Comment != null && p.Comment != null ? " / " : "") + p.Comment);
        }
    }
}
