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

namespace Elwig.Models.Dtos {
    public class MemberListData : DataTable<MemberListRow> {

        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),
            ("DefaultKg", "Stammgemeinde", null, 60),
            ("Branch", "Zweigstelle", null, 40),
            ("BusinessShares", "GA", null, 10),
            ("BillingName", "Rechnungsname", null, 60),
            ("BillingAddress", "Rechnungsadresse", null, 60),
            ("BillingPlz", "PLZ", null, 10),
            ("BillingLocality", "Ort", null, 60),
            ("LfbisNr", "Betr.-Nr.", null, 20),
            ("IsBuchführend", "buchf.", null, 15),
            ("IsOrganic", "Bio", null, 15),
            ("IsActive", "aktiv", null, 15),
            ("EntryDate", "Eintritt", null, 20),
            ("ExitDate", "Austritt", null, 20),
            ("AreaCommitment", "geb. Fläche", "m²", 20),
            ("UstIdNr", "UID", null, 25),
            ("Iban", "IBAN", null, 45),
            ("Bic", "BIC", null, 30),
            ("Comment", "Anmerkung", null, 60),
        ];

        public MemberListData(IEnumerable<MemberListRow> rows, List<string> filterNames) :
            base(MemberList.Name, MemberList.Name, string.Join(" / ", filterNames), rows, FieldNames) {
        }

        public static async Task<MemberListData> FromQuery(IQueryable<Member> query, List<string> filterNames) {
            var areaCom = await query.ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments).Sum(c => c.Area));
            return new((await query
                .Include(m => m.DefaultWbKg!.AtKg)
                .Include(m => m.Branch)
                .Include(m => m.PostalDest.AtPlz!.Ort)
                .Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
                .ToListAsync()).Select(m => new MemberListRow(m, areaCom[m.MgNr])), filterNames);
        }
    }

    public class MemberListRow {
        public int MgNr;
        public string? Name1;
        public string? Name2;
        public string? DefaultKg;
        public string? Branch;
        public int BusinessShares;
        public string Address;
        public int Plz;
        public string Locality;
        public string? BillingName;
        public string? BillingAddress;
        public int? BillingPlz;
        public string? BillingLocality;
        public string? LfbisNr;
        public string? UstIdNr;
        public string? Iban;
        public string? Bic;
        public int? AreaCommitment;
        public bool IsBuchführend;
        public bool IsOrganic;
        public bool IsActive;
        public DateOnly? EntryDate;
        public DateOnly? ExitDate;
        public string? Comment;

        public MemberListRow(Member m, int? areaCom = null) {
            MgNr = m.MgNr;
            Name1 = m.FamilyName;
            Name2 = m.AdministrativeName2;
            DefaultKg = m.DefaultKg?.Name;
            Branch = m.Branch?.Name;
            BusinessShares = m.BusinessShares;
            Address = m.Address;
            Plz = m.PostalDest.AtPlz!.Plz;
            Locality = m.PostalDest.AtPlz!.Ort.Name;
            if (m.BillingAddress is BillingAddr a) {
                BillingName = a.Name;
                BillingAddress = a.Address;
                BillingPlz = a.PostalDest.AtPlz!.Plz;
                BillingLocality = a.PostalDest.AtPlz!.Ort.Name;
            }
            LfbisNr = m.LfbisNr;
            UstIdNr = m.UstIdNr;
            Iban = m.Iban != null ? Utils.FormatIban(m.Iban) : null;
            Bic = m.Bic;
            IsBuchführend = m.IsBuchführend;
            IsOrganic = m.IsOrganic;
            IsActive = m.IsActive;
            EntryDate = m.EntryDate;
            ExitDate = m.ExitDate;
            Comment = m.Comment;
            AreaCommitment = areaCom == 0 ? null : areaCom;
        }
    }
}