using KarleyLibrary.Erweiterungen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using WK5.Core.Models;
using WK5.Core.Basis;

namespace WK5.Core.Services
{
    /// <summary>
    /// Stellt Funktionen zur Verwaltung von Vertretern und der Provisionsabrechnung zur Verfügung.
    /// </summary>
    public class VertreterService : IModelService<Vertreter, int>
    {
        /// <summary>
        /// Erstellt einen neuen Vertreter
        /// </summary>
        /// <param name="input"></param>
        /// <param name="fbController"></param>
        /// <returns></returns>
        public async Task CreateAsync(Vertreter input, FbController2 fbController)
        {
            fbController.AddParameter("@VERT_N_NR", input.VERT_N_NR);
            fbController.AddParameter("@VERT_A_NAME", input.VERT_A_NAME);
            fbController.AddParameter("@VERT_A_VORNAME", input.VERT_A_VORNAME);
            fbController.AddParameter("@VERT_N_PROVISION", input.VERT_N_PROVISION);
            fbController.AddParameter("@VERT_N_PERSONALNR", input.VERT_N_PERSONALNR);
            fbController.AddParameter("@VERT_L_INAKTIV", false);

            await fbController.QueryAsync(@"INSERT INTO VERTRETER 
(
VERT_N_NR, VERT_A_NAME, VERT_A_VORNAME, VERT_N_PROVISION, VERT_N_PERSONALNR, VERT_L_INAKTIV
)
VALUES
(
@VERT_N_NR, @VERT_A_NAME, @VERT_A_VORNAME, @VERT_N_PROVISION, @VERT_N_PERSONALNR, @VERT_L_INAKTIV
)");

            
        }
        /// <summary>
        /// Aktualisiert einen bestehenden Vertreter
        /// </summary>
        /// <param name="input"></param>
        /// <param name="fbController"></param>
        /// <returns></returns>
        public async Task UpdateAsync(Vertreter input, FbController2 fbController)
        {
            fbController.AddParameter("@VERT_N_NR", input.VERT_N_NR);
            fbController.AddParameter("@VERT_A_NAME", input.VERT_A_NAME);
            fbController.AddParameter("@VERT_A_VORNAME", input.VERT_A_VORNAME);
            fbController.AddParameter("@VERT_N_PROVISION", input.VERT_N_PROVISION);
            fbController.AddParameter("@VERT_N_PERSONALNR", input.VERT_N_PERSONALNR);
            fbController.AddParameter("@VERT_L_INAKTIV", input.VERT_L_INAKTIV);

            await fbController.QueryAsync(@"UPDATE VERTRETER SET
VERT_A_NAME = @VERT_A_NAME, VERT_A_VORNAME = @VERT_A_VORNAME, 
VERT_N_PROVISION = @VERT_N_PROVISION, VERT_N_PERSONALNR = @VERT_N_PERSONALNR, VERT_L_INAKTIV = @VERT_L_INAKTIV
WHERE
VERT_N_NR = @VERT_N_NR");

        }

        public Task<Vertreter?> GetAsync(int identifier, FbController2 fbController)
        {
            throw new NotImplementedException();
        }

        public Task<Vertreter> DeleteAsync(Vertreter input, FbController2 fbController)
        {
            throw new NotImplementedException();
        }

        public IAsyncEnumerable<Vertreter> GetAllAsync(FbController2 fbController)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Ruft die Provisionsabrechnung auf Basis des Umsatzes ab.
        /// <para>
        /// Die Logik stimmt 1:1 mit der der W4 überein.
        /// </para>
        /// <para>
        /// Ggf. stimmen die Zahlen hier nicht mehr durch die Einführung von Bundles.
        /// </para>
        /// </summary>
        /// <param name="von"></param>
        /// <param name="bis"></param>
        /// <param name="vertreterId"></param>
        /// <param name="fbController"></param>
        /// <returns></returns>
        public async IAsyncEnumerable<Provision> GetProvisionsabrechnungAsync(DateTime von, DateTime bis, int vertreterId, FbController2 fbController)
        {
            fbController.AddParameter("@VERT_N_NR", vertreterId);
            fbController.AddParameter("@START", von.ToShortDateString());
            fbController.AddParameter("@ENDE", bis.ToShortDateString());
            DataTable data = await fbController.SelectDataAsync("SELECT * FROM VIEW_UMSATZ_VERTRETER WHERE VERT_N_NR = @VERT_N_NR AND BELE_D_DATE BETWEEN @START AND @ENDE");

            foreach (DataRow row in data.Rows)
            {
                yield return ObjectErweiterung.DataRowZuObjekt(new Provision(), row);
            }

        }
        /// <summary>
        /// Ruft die Provisionsabrechnung für einen bestimmten Zeitraum eines Vertreters auf Basis des Roherlöses ab.
        /// <para>
        /// Diese Funktion befindet sich noch in der BETA und muss noch durch Ley geprüft werden.
        /// </para>
        /// </summary>
        /// <param name="von"></param>
        /// <param name="bis"></param>
        /// <param name="vertreterId"></param>
        /// <param name="fbController"></param>
        /// <returns></returns>
        public async IAsyncEnumerable<Provision> GetProvisionsAbrechnungAufBasisVonRoherlösAsync(DateTime von, DateTime bis, int vertreterId, FbController2 fbController)
        {
            //TODO: Für Ley überprüfen!!
            fbController.AddParameter("@VERT_N_NR", vertreterId);
            fbController.AddParameter("@START", von.ToShortDateString());
            fbController.AddParameter("@ENDE", bis.ToShortDateString());
            // MK für Ley:
            // Da keine Chargen mehr ausgewählt werden, kann es ggf. zu Abweichungen kommen, wenn ein Artikel zu einem neuen Preis verkauft wird.
            // Beispiel: Artikel für 50€ zugebucht, neuer Preis von Lieferanten sind nun 30€, es wurde eine Charge mit 50€ gebucht und der Artikel wurde für 40€ verkauft => -10€ * Prozentsatz
            // Das Problem ist bekannt kann aber nur gelöst werden, wenn bekannt ist welche Charge ausgebucht wird. Artikel mit Seriennummerführung sind davon nicht betroffen.
            // Besonders anfällig dafür ist DIVERS, wenn hier vergessen wird rechtzeitig auszubuchen!!!!!
            DataTable data = await fbController.SelectDataAsync(@"SELECT VERT_N_NR, VERT_N_PROVISION, BELE_D_DATE, 
CASE WHEN BELE_A_TYP = 'GU' THEN
     (PREIS_MIT_RABATT - SUM(NETTO)) * -1
ELSE
     PREIS_MIT_RABATT - SUM(NETTO)
END AS NETTO, 
BELE_A_TYP, 
BELE_N_NR, 
BELE_A_NAME1,
BPOS_N_POS
FROM (
SELECT 
VERT_N_NR, 
VERT_N_PROVISION, 
BELE_D_DATE,
CASE WHEN A.ARTI_L_BUNDLE = 'N' THEN
    CASE WHEN C.CHAR_N_EKPREIS IS NULL THEN
    BP.WK5_BPOS_N_EK * BP.BPOS_N_MENGE
ELSE
    C.CHAR_N_EKPREIS * BC.BCHA_N_MENGE
END
ELSE
    0
END AS NETTO, 
BELE_A_TYP, 
BELE_N_NR, 
BELE_A_NAME1,
BPOS_N_POS,
BPOS_N_POSID,
BC.BCHA_N_CHARGE,
C.CHAR_N_EKPREIS,
BPOS_N_MENGE * BPOS_N_PREIS * (100 - coalesce(BP.BPOS_N_RABATTPROZ, 0)) / 100 * (100 - coalesce(BP.BPOS_N_RABATTPROZ2, 0)) / 100 AS PREIS_MIT_RABATT
FROM
vertreter
left outer join belege b on ((bele_a_typ = 'RE' or bele_a_typ = 'GU') and bele_n_vertreter = VERT_N_NR)
LEFT JOIN LIEFERBEDINGUNG ON (LIBD_N_NR = BELE_N_LIEFERUNG)
LEFT JOIN BELEGPOS BP ON (BPOS_A_TYP = BELE_A_TYP AND BPOS_N_NR = BELE_N_NR)
LEFT JOIN BELEGCHARGEN BC ON (BC.BCHA_N_POSID = BP.BPOS_N_POSID)
LEFT JOIN CHARGEN C ON (C.CHAR_N_NR = BC.BCHA_N_CHARGE)
LEFT JOIN ARTIKEL A ON A.ARTI_A_NR = BP.BPOS_A_ARTIKELNR
LEFT JOIN ARTIKEL A2 ON A2.ARTI_A_NR = C.CHAR_A_ARTINR
WHERE BELE_A_TYP IN ('RE', 'GU') AND BELE_D_DATE BETWEEN @START AND @ENDE
AND BP.BPOS_A_ARTIKELNR NOT IN ('TEXT')
AND (A.ARTI_L_OHNE_PROV = 'N' OR (BP.BPOS_A_ARTIKELNR = 'VERSAND' AND LIBD_L_SPEDITION = 'Y'))
AND (COALESCE(A.ARTI_L_OHNE_PROV, 'N') = 'N' AND COALESCE(A2.ARTI_L_OHNE_PROV, 'N') = 'N')
AND VERT_N_NR = @VERT_N_NR)
GROUP BY VERT_N_NR, VERT_N_PROVISION, BELE_D_DATE, BELE_A_TYP, BELE_N_NR, BELE_A_NAME1, BPOS_N_POSID, PREIS_MIT_RABATT, BPOS_N_POS
");
            foreach (DataRow row in data.Rows)
            {
                yield return ObjectErweiterung.DataRowZuObjekt(new Provision(), row);
            }
        }
    }
}
