using KarleyLibrary.Erweiterungen;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WK5.Core.Basis;
using WK5.Core.Basis.Filter;
using WK5.Core.Models;

namespace WK5.Core.Services
{
    public class RmaService : IModelService<Rma, int>
    {
        public async Task<Rma?> GetAsync(int identifier, FbController2 fbController)
        {
            fbController.AddParameter("@RMA_N_NR", identifier);
            DataRow? row = await fbController.SelectRowAsync(@"SELECT 
R.*,
K.KUND_A_NAME1, K.KUND_A_NAME2, K.KUND_A_NAME3
FROM RMAS R 
LEFT JOIN KUNDEN K ON K.KUND_A_NR = R.RMA_A_KUNDENNR
WHERE RMA_N_NR = @RMA_N_NR");
            return row is null ? null : ObjectErweiterung.DataRowZuObjekt(new Rma(), row);
        }

        public async Task CreateAsync(Rma input, FbController2 fbController)
        {
            input.Anlagedatum = DateTime.Now;
            input.LetzteÄnderung = input.Anlagedatum;
            input.LetzterBearbeiterId = fbController.UserId;
            input.AnlageUserId = fbController.UserId;

            fbController.AddParameter("@RMA_N_LIEFNR", input.LieferantId);
            fbController.AddParameter("@RMA_N_LIEFADRESSE_LIEFERANT", input.LieferanschriftLieferantId);
            fbController.AddParameter("@RMA_A_PARTNER_LIEFERANT", input.LieferantAnsprechpartner);
            fbController.AddParameter("@RMA_A_PARTNER_EMAIL_LIEFERANT", input.LieferantAnsprechpartnerEmail);
            fbController.AddParameter("@RMA_A_KUNDENNR", input.Kundennummer);
            fbController.AddParameter("@RMA_N_LIEFADRESSE_KUNDE", input.LieferanschriftKundeId);
            fbController.AddParameter("@RMA_A_PARTNER_KUNDE", input.KundeAnsprechpartner);
            fbController.AddParameter("@RMA_A_PARTNER_EMAIL_KUNDE", input.KundeAnsprechpartnerEmail);
            fbController.AddParameter("@RMA_N_BELEPOSID", input.BelegposId);
            fbController.AddParameter("@RMA_N_STLPOSID", input.StücklistenPositionsId);
            fbController.AddParameter("@RMA_N_BELEGCHARGE", input.BelegChargenId);
            fbController.AddParameter("@RMA_A_ARTIKELNR", input.Artikelnummer);
            fbController.AddParameter("@RMA_A_SERIENNUMMER", input.Seriennummer);
            fbController.AddParameter("@RMA_N_MENGE", input.Menge);
            fbController.AddParameter("@RMA_D_ANLAGEDATUM", input.Anlagedatum);
            fbController.AddParameter("@RMA_N_NR_LS", input.LieferscheinNummer);
            fbController.AddParameter("@RMA_B_NOTIZ", input.Notiz);
            fbController.AddParameter("@RMA_B_FEHLERANGABE_KUNDE", input.FehlerangabeKunde);
            fbController.AddParameter("@RMA_B_KUNDENHINWEISE", input.Kundenhinweise);
            fbController.AddParameter("@RMA_B_FEHLERANGABE_LIEFERANT", input.FehlerangabeLieferant);
            fbController.AddParameter("@RMA_B_RUECKLIEFERINFO", input.RücklieferInfo);
            fbController.AddParameter("@RMA_A_RMANR_LIEFERANT", input.RmaNummerLieferant);
            fbController.AddParameter("@RMA_A_TICKETNR_LIEFERANT", input.TicketNummerLieferant);
            fbController.AddParameter("@RMA_A_TICKETNR", input.TicketNummer);
            fbController.AddParameter("@RMA_L_DIREKT_AN_KUNDE", input.RückversandVonLieferantDirektZumKunden);
            fbController.AddParameter("@RMA_L_DIREKT_AN_LIEFERANT", input.RückversandVonKundeDirektZumLieferant);
            fbController.AddParameter("@RMA_L_EIGENBESTAND", input.Eigenbestand);
            fbController.AddParameter("@RMA_N_ANLAGEUSER", input.AnlageUserId);
            fbController.AddParameter("@RMA_N_LASTUSER", input.LetzterBearbeiterId);
            fbController.AddParameter("@RMA_TIMESTAMP", input.LetzteÄnderung);


            input.Id = Convert.ToInt32(await fbController.FetchObjectAsync(@"INSERT INTO RMAS
(
RMA_N_LIEFNR, 
RMA_N_LIEFADRESSE_LIEFERANT, 
RMA_A_PARTNER_LIEFERANT, 
RMA_A_PARTNER_EMAIL_LIEFERANT, 
RMA_A_KUNDENNR, 
RMA_N_LIEFADRESSE_KUNDE, 
RMA_A_PARTNER_KUNDE,
RMA_A_PARTNER_EMAIL_KUNDE,
RMA_N_BELEPOSID, 
RMA_N_STLPOSID, 
RMA_N_BELEGCHARGE, 
RMA_A_ARTIKELNR, 
RMA_A_SERIENNUMMER,
RMA_N_MENGE, 
RMA_D_ANLAGEDATUM, 
RMA_N_NR_LS, 
RMA_B_NOTIZ, 
RMA_B_FEHLERANGABE_KUNDE,
RMA_B_KUNDENHINWEISE,
RMA_B_FEHLERANGABE_LIEFERANT,
RMA_B_RUECKLIEFERINFO, 
RMA_A_RMANR_LIEFERANT, 
RMA_A_TICKETNR_LIEFERANT, 
RMA_A_TICKETNR,
RMA_L_DIREKT_AN_KUNDE, 
RMA_L_DIREKT_AN_LIEFERANT,
RMA_L_EIGENBESTAND,
RMA_N_ANLAGEUSER, 
RMA_N_LASTUSER, 
RMA_TIMESTAMP
)
VALUES
(
@RMA_N_LIEFNR, 
@RMA_N_LIEFADRESSE_LIEFERANT, 
@RMA_A_PARTNER_LIEFERANT, 
@RMA_A_PARTNER_EMAIL_LIEFERANT, 
@RMA_A_KUNDENNR, 
@RMA_N_LIEFADRESSE_KUNDE, 
@RMA_A_PARTNER_KUNDE,
@RMA_A_PARTNER_EMAIL_KUNDE,
@RMA_N_BELEPOSID, 
@RMA_N_STLPOSID, 
@RMA_N_BELEGCHARGE, 
@RMA_A_ARTIKELNR,
@RMA_A_SERIENNUMMER,
@RMA_N_MENGE,
@RMA_D_ANLAGEDATUM, 
@RMA_N_NR_LS, 
@RMA_B_NOTIZ, 
@RMA_B_FEHLERANGABE_KUNDE, 
@RMA_B_KUNDENHINWEISE,
@RMA_B_FEHLERANGABE_LIEFERANT,
@RMA_B_RUECKLIEFERINFO, 
@RMA_A_RMANR_LIEFERANT, 
@RMA_A_TICKETNR_LIEFERANT, 
@RMA_A_TICKETNR,
@RMA_L_DIREKT_AN_KUNDE, 
@RMA_L_DIREKT_AN_LIEFERANT,
@RMA_L_EIGENBESTAND,
@RMA_N_ANLAGEUSER, 
@RMA_N_LASTUSER, 
@RMA_TIMESTAMP
) RETURNING RMA_N_NR"));
        }
        public async Task UpdateAsync(Rma input, FbController2 fbController)
        {


            input.LetzteÄnderung = DateTime.Now;
            input.LetzterBearbeiterId = fbController.UserId;

            fbController.AddParameter("@RMA_N_LIEFADRESSE_LIEFERANT", input.LieferanschriftLieferantId);
            fbController.AddParameter("@RMA_A_PARTNER_LIEFERANT", input.LieferantAnsprechpartner);
            fbController.AddParameter("@RMA_A_PARTNER_EMAIL_LIEFERANT", input.LieferantAnsprechpartnerEmail);
            fbController.AddParameter("@RMA_N_LIEFADRESSE_KUNDE", input.LieferanschriftKundeId);
            fbController.AddParameter("@RMA_A_PARTNER_KUNDE", input.KundeAnsprechpartner);
            fbController.AddParameter("@RMA_A_PARTNER_EMAIL_KUNDE", input.KundeAnsprechpartnerEmail);
            fbController.AddParameter("@RMA_N_MENGE", input.Menge);
            fbController.AddParameter("@RMA_L_GARANTIE", input.Garantie);
            fbController.AddParameter("@RMA_L_GARANTIE_LF", input.GarantieLieferant);
            fbController.AddParameter("@RMA_L_ERLEDIGT", input.Erledigt);
            fbController.AddParameter("@RMA_B_NOTIZ", input.Notiz);
            fbController.AddParameter("@RMA_B_FEHLERANGABE_KUNDE", input.FehlerangabeKunde);
            fbController.AddParameter("@RMA_B_KUNDENHINWEISE", input.Kundenhinweise);
            fbController.AddParameter("@RMA_B_FEHLERANGABE_LIEFERANT", input.FehlerangabeLieferant);
            fbController.AddParameter("@RMA_B_RUECKLIEFERINFO", input.RücklieferInfo);
            fbController.AddParameter("@RMA_A_RMANR_LIEFERANT", input.RmaNummerLieferant);
            fbController.AddParameter("@RMA_A_TICKETNR_LIEFERANT", input.TicketNummerLieferant);
            fbController.AddParameter("@RMA_A_TICKETNR", input.TicketNummer);
            fbController.AddParameter("@RMA_N_NEWZUGANG", input.NewZugangId);
            fbController.AddParameter("@RMA_L_RUECKSENDUNG_KUNDE", input.RücksendungAngefordert);
            fbController.AddParameter("@RMA_D_RUECKSENDUNG_KUNDE", input.RücksendungAngefordertDatum);
            fbController.AddParameter("@RMA_L_ANFRAGE_LIEFERANT", input.AnfrageLieferant);
            fbController.AddParameter("@RMA_D_ANFRAGE_LIEFERANT", input.AnfrageLieferantDatum);
            fbController.AddParameter("@RMA_L_EINGANGSBELEG", input.Eingangsbeleg);
            fbController.AddParameter("@RMA_D_EINGANGSBELEG", input.EingangsbelegDatum);
            fbController.AddParameter("@RMA_L_RUECKSENDUNG_LIEFERANT", input.RücksendungAnLieferant);
            fbController.AddParameter("@RMA_D_RUECKSENDUNG_LIEFERANT", input.RücksendungAnLieferantDatum);
            fbController.AddParameter("@RMA_L_ZURUECK_LIEFERANT", input.ZurückVonLieferant);
            fbController.AddParameter("@RMA_D_ZURUECK_LIEFERANT", input.ZurückVonLieferantDatum);
            fbController.AddParameter("@RMA_L_ZURUECK_KUNDE", input.ZurückAnKunde);
            fbController.AddParameter("@RMA_D_ZURUECK_KUNDE", input.ZurückAnKundeDatum);
            fbController.AddParameter("@RMA_L_LIEFERANTENBELASTUNG", input.Lieferantenbelastung);
            fbController.AddParameter("@RMA_D_LIEFERANTENBELASTUNG", input.LieferantenbelastungDatum);
            fbController.AddParameter("@RMA_L_GUTSCHRIFT_LF", input.GutschriftVonLieferant);
            fbController.AddParameter("@RMA_A_GUTSCHRIFT_LF", input.GutschriftVonLieferantNummer);
            fbController.AddParameter("@RMA_L_DIREKT_AN_KUNDE", input.RückversandVonLieferantDirektZumKunden);
            fbController.AddParameter("@RMA_L_DIREKT_AN_LIEFERANT", input.RückversandVonKundeDirektZumLieferant);
            fbController.AddParameter("@RMA_L_EIGENBESTAND", input.Eigenbestand);
            fbController.AddParameter("@RMA_N_LASTUSER", input.LetzterBearbeiterId);
            fbController.AddParameter("@RMA_TIMESTAMP", input.LetzteÄnderung);
            fbController.AddParameter("@RMA_N_NR", input.Id);


            await fbController.QueryAsync(@"UPDATE RMAS SET
RMA_N_LIEFADRESSE_LIEFERANT = @RMA_N_LIEFADRESSE_LIEFERANT, 
RMA_A_PARTNER_LIEFERANT = @RMA_A_PARTNER_LIEFERANT,
RMA_A_PARTNER_EMAIL_LIEFERANT = @RMA_A_PARTNER_EMAIL_LIEFERANT,
RMA_N_LIEFADRESSE_KUNDE = @RMA_N_LIEFADRESSE_KUNDE,
RMA_A_PARTNER_KUNDE = @RMA_A_PARTNER_KUNDE,
RMA_A_PARTNER_EMAIL_KUNDE = @RMA_A_PARTNER_EMAIL_KUNDE,
RMA_N_MENGE = @RMA_N_MENGE, 
RMA_L_GARANTIE = @RMA_L_GARANTIE,
RMA_L_GARANTIE_LF = @RMA_L_GARANTIE_LF,
RMA_L_ERLEDIGT = @RMA_L_ERLEDIGT,
RMA_B_NOTIZ = @RMA_B_NOTIZ, 
RMA_B_FEHLERANGABE_KUNDE = @RMA_B_FEHLERANGABE_KUNDE, 
RMA_B_KUNDENHINWEISE = @RMA_B_KUNDENHINWEISE,
RMA_B_FEHLERANGABE_LIEFERANT = @RMA_B_FEHLERANGABE_LIEFERANT,
RMA_B_RUECKLIEFERINFO = @RMA_B_RUECKLIEFERINFO, 
RMA_A_RMANR_LIEFERANT = @RMA_A_RMANR_LIEFERANT, 
RMA_A_TICKETNR_LIEFERANT = @RMA_A_TICKETNR_LIEFERANT, 
RMA_A_TICKETNR = @RMA_A_TICKETNR,
RMA_N_NEWZUGANG = @RMA_N_NEWZUGANG,
RMA_L_RUECKSENDUNG_KUNDE = @RMA_L_RUECKSENDUNG_KUNDE,
RMA_D_RUECKSENDUNG_KUNDE = @RMA_D_RUECKSENDUNG_KUNDE,
RMA_L_EINGANGSBELEG = @RMA_L_EINGANGSBELEG,
RMA_D_EINGANGSBELEG = @RMA_D_EINGANGSBELEG,
RMA_L_ANFRAGE_LIEFERANT = @RMA_L_ANFRAGE_LIEFERANT,
RMA_D_ANFRAGE_LIEFERANT = @RMA_D_ANFRAGE_LIEFERANT,
RMA_L_RUECKSENDUNG_LIEFERANT = @RMA_L_RUECKSENDUNG_LIEFERANT,
RMA_D_RUECKSENDUNG_LIEFERANT = @RMA_D_RUECKSENDUNG_LIEFERANT,
RMA_L_ZURUECK_LIEFERANT = @RMA_L_ZURUECK_LIEFERANT,
RMA_D_ZURUECK_LIEFERANT = @RMA_D_ZURUECK_LIEFERANT,
RMA_L_ZURUECK_KUNDE = @RMA_L_ZURUECK_KUNDE,
RMA_D_ZURUECK_KUNDE = @RMA_D_ZURUECK_KUNDE,
RMA_L_LIEFERANTENBELASTUNG = @RMA_L_LIEFERANTENBELASTUNG,
RMA_D_LIEFERANTENBELASTUNG = @RMA_D_LIEFERANTENBELASTUNG,
RMA_L_GUTSCHRIFT_LF = @RMA_L_GUTSCHRIFT_LF,
RMA_A_GUTSCHRIFT_LF = @RMA_A_GUTSCHRIFT_LF,
RMA_L_DIREKT_AN_KUNDE = @RMA_L_DIREKT_AN_KUNDE,
RMA_L_DIREKT_AN_LIEFERANT = @RMA_L_DIREKT_AN_LIEFERANT,
RMA_L_EIGENBESTAND = @RMA_L_EIGENBESTAND,
RMA_N_LASTUSER = @RMA_N_LASTUSER, 
RMA_TIMESTAMP = @RMA_TIMESTAMP
WHERE RMA_N_NR = @RMA_N_NR");


        }
        public async Task SetAustauschTypAsync(int rmaId, int typ, FbController2 fbController)
        {
            if (typ is < 0 or > 3)
            {
                throw new ArgumentOutOfRangeException(nameof(typ), $"'{nameof(typ)}' muss zwischen 0 und 3 liegen");
            }

            fbController.AddParameter("@RMA_N_AUSTAUSCHTYP", typ);
            fbController.AddParameter("@RMA_N_NR", rmaId);
            await fbController.QueryAsync("UPDATE RMAS SET RMA_N_AUSTAUSCHTYP = @RMA_N_AUSTAUSCHTYP WHERE RMA_N_NR = @RMA_N_NR");
        }
        public async Task SetRmaZugangAsync(int rmaId, int zugangId, FbController2 fbController)
        {
            fbController.AddParameter("@RMA_N_NEWZUGANG", zugangId);
            fbController.AddParameter("@RMA_N_NR", rmaId);
            await fbController.QueryAsync("UPDATE RMAS SET RMA_N_NEWZUGANG = @RMA_N_NEWZUGANG WHERE RMA_N_NR = @RMA_N_NR");
        }
        public async Task SetZurückVonLieferant(int rmaId, FbController2 fbController)
        {
            fbController.AddParameter("@RMA_N_NR", rmaId);
            await fbController.QueryAsync("UPDATE RMAS SET RMA_L_ZURUECK_LIEFERANT = 'Y', RMA_D_ZURUECK_LIEFERANT = CURRENT_TIMESTAMP WHERE RMA_N_NR = @RMA_N_NR");
        }
        public async IAsyncEnumerable<(string belegtyp, int belegnummer)> GetRmaBelegeAsync(int rmaId, FbController2 fbController, [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            fbController.AddParameter("@BELE_N_NR_RMA", rmaId);
            DataTable data = await fbController.SelectDataAsync("SELECT DISTINCT BELE_N_NR, BELE_A_TYP FROM BELEGE WHERE BELE_N_NR_RMA = @BELE_N_NR_RMA ORDER BY BELE_D_DATE DESC, BELE_N_NR DESC", cancellationToken);

            foreach (DataRow row in data.Rows)
            {
                cancellationToken.ThrowIfCancellationRequested();

                string belegtyp = row.Field<string>("BELE_A_TYP") ?? string.Empty;
                int belegnummer = row.Field<int>("BELE_N_NR");

                yield return (belegtyp, belegnummer);
            }

            
        }

        #region RmaÜbersicht
        public async IAsyncEnumerable<Rma> GetRmasAsync(RmaFilter filter, FbController2 fbController, [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            DataTable data = await fbController.SelectDataAsync(filter.ToSqlQuery(fbController), cancellationToken);

            foreach (DataRow row in data.Rows)
            {
                cancellationToken.ThrowIfCancellationRequested();

                yield return ObjectErweiterung.DataRowZuObjekt(new Rma(), row);
            }
        }

        public async Task<int> GetAnzahlRmasAsync(RmaFilter filter, FbController2 fbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            int anzahl = Convert.ToInt32(await fbController.FetchObjectAsync(filter.ToCountQuery(fbController), cancellationToken));
            return anzahl;
        }
        #endregion
        #region RmaVerlauf
        public async Task<List<RmaVerlauf>> GetVerlaufAsync(RmaVerlaufFilter filter, FbController2 fbController, CancellationToken token = default)
        {
            return await fbController.SelectDataAsync<RmaVerlauf>(filter.ToSqlQuery(fbController), new
            {
                SUCHBEGRIFF = $"%{filter.Suchbegriff}%",
                RMVE_N_RMA_NR = filter.RmaNummer,
                RMVE_N_LASTUSER = filter.UserId
            });
        }

        public async Task CreateRmaVerlaufAsync(RmaVerlauf verlauf, FbController2 fbController)
        {
            verlauf.RMVE_TIMESTAMP = DateTime.Now;
            verlauf.RMVE_N_LASTUSER = fbController.UserId;
            fbController.AddParameter("@RMVE_N_RMA_NR", verlauf.RMVE_N_RMA_NR);
            fbController.AddParameter("@RMVE_A_TEXT", verlauf.RMVE_A_TEXT);
            fbController.AddParameter("@RMVE_TIMESTAMP", verlauf.RMVE_TIMESTAMP);
            fbController.AddParameter("@RMVE_N_LASTUSER",verlauf.RMVE_N_LASTUSER);
            verlauf.RMVE_N_ID = Convert.ToInt32(await fbController.FetchObjectAsync(@"INSERT INTO RMA_VERLAUF
(
RMVE_N_RMA_NR,
RMVE_A_TEXT,
RMVE_TIMESTAMP,
RMVE_N_LASTUSER
)
VALUES
(
@RMVE_N_RMA_NR,
@RMVE_A_TEXT,
@RMVE_TIMESTAMP,
@RMVE_N_LASTUSER
)
RETURNING RMVE_N_ID"));
        }
        
        public async Task UpdateRmaVerlaufAsync(RmaVerlauf verlauf, FbController2 fbController)
        {
            verlauf.RMVE_TIMESTAMP = DateTime.Now;
            verlauf.RMVE_N_LASTUSER = fbController.UserId;
            fbController.AddParameter("@RMVE_N_RMA_NR", verlauf.RMVE_N_RMA_NR);
            fbController.AddParameter("@RMVE_A_TEXT", verlauf.RMVE_A_TEXT);
            fbController.AddParameter("@RMVE_TIMESTAMP", verlauf.RMVE_TIMESTAMP);
            fbController.AddParameter("@RMVE_N_LASTUSER", verlauf.RMVE_N_LASTUSER);
            fbController.AddParameter("@RMVE_N_ID", verlauf.RMVE_N_ID);
            
            await fbController.QueryAsync(@"UPDATE RMA_VERLAUF SET
RMVE_N_RMA_NR = @RMVE_N_RMA_NR,
RMVE_A_TEXT = @RMVE_A_TEXT,
RMVE_TIMESTAMP = @RMVE_TIMESTAMP,
RMVE_N_LASTUSER = @RMVE_N_LASTUSER
WHERE RMVE_N_ID = @RMVE_N_ID");
        }
        #endregion
    }
}
