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.Basis;
using WK5.Core.Models;

namespace WK5.Core.Services
{
    /// <summary>
    /// Dieser Service hat noch keinen Sinn,da die ArtikelOptionen noch nicht fertig programmiert wurden. Wird wahrscheinlich verworfen
    /// </summary>
    public class ArtikelOptionenService : IModelService<ArtikelOption, int>
    {
        public async Task<ArtikelOption?> GetAsync(int identifier, FbController2 fbController)
        {
            fbController.AddParameter("@AROP_N_NR", identifier);
            DataRow? row = await fbController.SelectRowAsync("SELECT * FROM ARTIKEL_OPTIONEN WHERE AROP_N_NR = @AROP_N_NR");

            if (row is null)
            {
                return null;
            }

            ArtikelOption option = ObjectErweiterung.DataRowZuObjekt(new ArtikelOption(), row);

            if (option.Typ is "select")
            {
                fbController.AddParameter("@AROV_N_OPTIONNR", option.Id);
                DataTable valueData = await fbController.SelectDataAsync("SELECT * FROM ARTIKEL_OPTIONEN_VALUE WHERE AROV_N_OPTIONNR = @AROV_N_OPTIONNR");

                foreach (DataRow valueRow in valueData.Rows)
                {
                    option.OptionValues.Add(ObjectErweiterung.DataRowZuObjekt(new ArtikelOptionValue(), valueRow));
                }
            }

            return option;
        }

        public async IAsyncEnumerable<ArtikelOption> GetAsync(FbController2 fbController)
        {
            DataTable data = await fbController.SelectDataAsync("SELECT * FROM ARTIKEL_OPTIONEN");

            foreach (DataRow row in data.Rows)
            {
                ArtikelOption option = ObjectErweiterung.DataRowZuObjekt(new ArtikelOption(), row);

                if (option.Typ is "select")
                {
                    fbController.AddParameter("@AROV_N_OPTIONNR", option.Id);
                    DataTable valueData = await fbController.SelectDataAsync("SELECT * FROM ARTIKEL_OPTIONEN_VALUE WHERE AROV_N_OPTIONNR = @AROV_N_OPTIONNR");

                    foreach (DataRow valueRow in valueData.Rows)
                    {
                        option.OptionValues.Add(ObjectErweiterung.DataRowZuObjekt(new ArtikelOptionValue(), valueRow));
                    }
                }

                yield return option;
            }



        }
        public async Task CreateAsync(ArtikelOption input, FbController2 fbController)
        {
            MinMaxKorrigieren(input);

            fbController.AddParameter("@AROP_A_NAME", input.Name);
            fbController.AddParameter("@AROP_A_TYP", input.Typ);
            fbController.AddParameter("@AROP_N_MINVALUE", input.MinValue);
            fbController.AddParameter("@AROP_N_MAXVALUE", input.MaxValue);
            fbController.AddParameter("@AROP_N_ORDER", input.SortOrder);
            input.Id = Convert.ToInt32(await fbController.FetchObjectAsync(@"INSERT INTO ARTIKEL_OPTIONEN
(
AROP_A_NAME,
AROP_A_TYP,
AROP_N_MINVALUE,
AROP_N_MAXVALUE,
AROP_N_ORDER
)
VALUES
(
@AROP_A_NAME,
@AROP_A_TYP,
@AROP_N_MINVALUE,
@AROP_N_MAXVALUE,
@AROP_N_ORDER
) RETURNING AROP_N_NR"));

            await CreateOptionValuesAsync(input, fbController);
        }
        public async Task UpdateAsync(ArtikelOption input, FbController2 fbController)
        {
            MinMaxKorrigieren(input);

            fbController.AddParameter("@AROP_A_NAME", input.Name);
            fbController.AddParameter("@AROP_A_TYP", input.Typ);
            fbController.AddParameter("@AROP_N_MINVALUE", input.MinValue);
            fbController.AddParameter("@AROP_N_MAXVALUE", input.MaxValue);
            fbController.AddParameter("@AROP_N_ORDER", input.SortOrder);
            fbController.AddParameter("@AROP_N_NR", input.Id);
            await fbController.QueryAsync(@"UPDATE ARTIKEL_OPTIONEN SET
AROP_A_NAME = @AROP_A_NAME,
AROP_A_TYP = @AROP_A_TYP,
AROP_N_MINVALUE = @AROP_N_MINVALUE,
AROP_N_MAXVALUE = @AROP_N_MAXVALUE,
AROP_N_ORDER = @AROP_N_ORDER
WHERE AROP_N_NR = @AROP_N_NR");

            fbController.AddParameter("@AROV_N_OPTIONNR", input.Id);
            await fbController.QueryAsync("DELETE FROM ARTIKEL_OPTIONEN_VALUE WHERE AROV_N_OPTIONNR = @AROV_N_OPTIONNR");

            await CreateOptionValuesAsync(input, fbController);



        }
    
        public async Task DeleteAsync(ArtikelOption input, FbController2 fbController)
        {
            fbController.AddParameter("@AROV_N_OPTIONNR", input.Id);
            await fbController.QueryAsync("DELETE FROM ARTIKEL_OPTIONEN_VALUE WHERE AROV_N_OPTIONNR = @AROV_N_OPTIONNR");

            fbController.AddParameter("@AZUO_N_OPTION", input.Id);
            await fbController.QueryAsync("DELETE FROM ARTIKELTYP_ZU_OPTION WHERE AZUO_N_OPTION = @AZUO_N_OPTION");

            fbController.AddParameter("@AROP_N_NR", input.Id);
            await fbController.QueryAsync("DELETE FROM ARTIKEL_OPTIONEN WHERE AROP_N_NR = @AROP_N_NR");
        }
        private async Task CreateOptionValuesAsync(ArtikelOption input, FbController2 fbController)
        {
            if (input.Typ is "select")
            {
                foreach (var optionValue in input.OptionValues)
                {
                    optionValue.OptionId = input.Id;
                    fbController.AddParameter("@AROV_N_OPTIONNR", optionValue.OptionId);
                    fbController.AddParameter("@AROV_A_NAME", optionValue.Name);
                    fbController.AddParameter("@AROV_N_ORDER", optionValue.SortOrder);
                    optionValue.Id = Convert.ToInt32(await fbController.FetchObjectAsync(@"INSERT INTO ARTIKEL_OPTIONEN_VALUE
(
AROV_N_OPTIONNR,
AROV_A_NAME,
AROV_N_ORDER
)
VALUES
(
@AROV_N_OPTIONNR,
@AROV_A_NAME,
@AROV_N_ORDER
) RETURNING AROV_N_NR"));
                }
            }
        }
        private void MinMaxKorrigieren(ArtikelOption input)
        {
            // MinValue und MaxValue gibt es nur beim typ "number"
            if (input.Typ is not "number")
            {
                input.MinValue = 0;
                input.MaxValue = 0;
            }
        }
    }
}
