using KarleyLibrary.Erweiterungen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WK5.Core.Models;
using WK5.Core.PageModels.Tools;

namespace WK5.Core.Services
{
    public class ZahlungsPrüfungsService
    {
        public async IAsyncEnumerable<Beleg> SucheBelegeAsync(string Suchbegriff)
        {
            using FbController2 fbController = new FbController2();


            string[] splitParts = Suchbegriff.Split(' ', StringSplitOptions.RemoveEmptyEntries);

            if (splitParts.Where(x => !String.IsNullOrWhiteSpace(x) && Int32.TryParse(x, out int tmp) && tmp > 10000).Any())
            {
                List<string> sqlParts = new List<string>();

                int iterator = 1;
                foreach (string part in splitParts)
                {
                    if (!String.IsNullOrWhiteSpace(part))
                    {
                        if (Int32.TryParse(part, out int partNr))
                        {
                            if (partNr < 10000) continue;

                            string sqlPart = @$"(CAST(BELE_N_NR AS VARCHAR(255)) LIKE @SUCHE{iterator} OR CAST(BELE_A_BESTAET_NR AS VARCHAR(255)) LIKE @SUCHE{iterator}ONLINE)";
                            fbController.AddParameter($"@SUCHE{iterator}", $"%{partNr}%");
                            fbController.AddParameter($"@SUCHE{iterator}ONLINE", $"%KL-{partNr}%");
                            iterator++;

                            sqlParts.Add(sqlPart);
                        }
                    }
                }


                string sql = @$"SELECT * FROM BELEGE WHERE ({String.Join(" OR ", sqlParts)})
AND BELE_A_TYP IN ('AU','RE')";

                DataTable data = await fbController.SelectDataAsync(sql);

                foreach (DataRow row in data.Rows)
                {
                    Beleg? beleg = EnumHelper.GetBelegTyp(row.Field<string>("BELE_A_TYP")!) switch
                    {
                        BelegTyp.Auftrag => ObjectErweiterung.DataRowZuObjekt(new Auftrag(), row),
                        BelegTyp.Lieferschein => ObjectErweiterung.DataRowZuObjekt(new Lieferschein(), row),
                        BelegTyp.Rechnung => ObjectErweiterung.DataRowZuObjekt(new Rechnung(), row),
                        BelegTyp.Angebot => ObjectErweiterung.DataRowZuObjekt(new Angebot(), row),
                        BelegTyp.Gutschrift => ObjectErweiterung.DataRowZuObjekt(new Gutschrift(), row),
                        _ => null
                    };


                    if (beleg is not null)
                    {
                        await beleg.LadePositionenAsync(fbController);
                        yield return beleg;
                    }
                }
            }
        }

        public async Task<Beleg?> GetZahlBeleg(Beleg b)
        {
            using FbController2 fbController = new FbController2();
            var zahlungsbedingungen = await Zahlungsbedingung.GetZahlungsbedingungenAsync(fbController);
            if (zahlungsbedingungen.IstVorkasse(b.ZahlungsbedingungId))
            {
                if (b is Auftrag)
                {
                    return b;
                }
                else
                {
                    return await Auftrag.GetAuftragAsync(b.AuftragsnummerVerknüpfung, fbController);
                }
            }
            else if (zahlungsbedingungen.IstRechnung(b.ZahlungsbedingungId))
            {
                if (b is Rechnung)
                {
                    return b;
                }
                else
                {
                    return await Rechnung.GetRechnungAsync(b.RechnungsnummerVerknüpfung, fbController);
                }
            }
            return null;
        }

        public async Task SetBezahlt(Beleg beleg, ZahlungsPrüfungInput input, FbController2 fbController)
        {
            string sql = @"UPDATE BELEGE SET 
WK5_BELE_N_BEZAHLT_WERT = @WK5_BELE_N_BEZAHLT_WERT, 
WK5_BELE_D_BEZAHLT_DATUM = @WK5_BELE_D_BEZAHLT_DATUM, 
WK5_BELE_A_ZAHL_KOMMENTAR = @WK5_BELE_A_ZAHL_KOMMENTAR,
BELE_L_BEZAHLT = @BELE_L_BEZAHLT
WHERE BELE_N_NR = @BELE_N_NR AND BELE_A_TYP = @BELE_A_TYP";

            OptionCollection optC = await Option.GetOptionenAsync(fbController);
            Mehrwertsteuer? vMWst = await Mehrwertsteuer.GetVersandMehrwertsteuerAsync(fbController);

            fbController.AddParameter("@WK5_BELE_N_BEZAHLT_WERT", input.Zahlbetrag);
            fbController.AddParameter("@WK5_BELE_D_BEZAHLT_DATUM", input.Zahldatum);
            fbController.AddParameter("@WK5_BELE_A_ZAHL_KOMMENTAR", input.Zahltext);



            decimal sollBetrag = beleg.GetBruttoBetrag(optC, vMWst);

            List<int> skonti = new List<int>();
            if (beleg is Auftrag)
            {
                Auftrag? auftrag = beleg as Auftrag;
                if (auftrag is not null)
                {
                    if (await auftrag.SkontoZielErreicht(input.Zahldatum))
                    {
                        skonti = await auftrag.GetSkontoProzente(input.Zahldatum).ToListAsync();                        
                    }
                }
            }
            else if (beleg is Rechnung)
            {
                Rechnung? rechnung = beleg as Rechnung;
                if (rechnung is not null)
                {
                    if (await rechnung.SkontoZielErreicht(input.Zahldatum))
                    {
                        skonti = await rechnung.GetSkontoProzente(input.Zahldatum).ToListAsync();
                    }
                }
            }

            foreach(int skonto in skonti)
            {
                decimal percentage = 1.0m - ((decimal)skonto / 100.0m);
                sollBetrag *= percentage;
            }                        

            bool bezahlt = false;
            if (input.Zahlbetrag >= sollBetrag - 0.5m)
            {
                bezahlt = true;
            }

            fbController.AddParameter("@BELE_L_BEZAHLT", bezahlt);

            fbController.AddParameter("@BELE_N_NR", beleg.Belegnummer);
            fbController.AddParameter("@BELE_A_TYP", beleg.Belegtyp);

            await fbController.QueryAsync(sql);
        }
    }
}
