using KarleyLibrary.Erweiterungen;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace WK5.Core.Models
{
    public class ArtikelBild
    {
#if RELEASE
        public static string LocalImageDirectory = @"C:\inetpub\wwwroot\wk5\wwwroot\assets\img\artikel";
#elif DEBUG
        public static string LocalImageDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../", "WK5-Blazor/wwwroot/assets/img/artikel");
#endif

        public static string IISImageDisplayRoot = "assets/img/artikel";

        private static string RemoteImageDirectory = "httpdocs/image/";

        public int ARBI_N_NR { get; set; }
        public string ARBI_A_ARTINR { get; set; } = String.Empty;
        public string ARBI_A_IMGPFAD { get; set; } = String.Empty;
        public bool ARBI_L_HAUPT { get; set; }
        public DateTime ARBI_D_DATE { get; set; }

        public string WebImage
        {
            get
            {
                return String.IsNullOrWhiteSpace(ARBI_A_IMGPFAD) ? String.Empty : "/" + Path.Combine(IISImageDisplayRoot, ARBI_A_IMGPFAD.TrimStart('/').TrimStart('\\')).Replace("\\", "/");
            }
        }

        public string DriveImage
        {
            get
            {
                return FormatPath(Path.GetFullPath(Path.Combine(Path.GetFullPath(LocalImageDirectory), FormatPath(ARBI_A_IMGPFAD))));
            }
        }

        public static string FormatPath(string path)
        {
            return path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).TrimStart(Path.DirectorySeparatorChar);
        }

        private static async IAsyncEnumerable<ArtikelBild> GetArtikelBilderAsync()
        {
            using FbController2 fbController = new FbController2();

            DataTable data = await fbController.SelectDataAsync("SELECT * FROM WK5_ARTIKELBILDER");
            foreach (DataRow row in data.Rows)
            {
                if (row is not null)
                {
                    yield return ObjectErweiterung.DataRowZuObjekt(new ArtikelBild(), row);
                }
            }
        }

        private static async IAsyncEnumerable<ArtikelBild> GetArtikelBilderAsync(string ARTI_A_NR)
        {
            using FbController2 fbController = new FbController2();

            fbController.AddParameter("@ARBI_A_ARTINR", ARTI_A_NR);

            DataTable data = await fbController.SelectDataAsync("SELECT * FROM WK5_ARTIKELBILDER WHERE ARBI_A_ARTINR = @ARBI_A_ARTINR");
            foreach (DataRow row in data.Rows)
            {
                if (row is not null)
                {
                    yield return ObjectErweiterung.DataRowZuObjekt(new ArtikelBild(), row);
                }
            }
        }

        public static async Task<ArtikelBild> CreateAsync(ArtikelBild bild)
        {
            using FbController2 fbController = new FbController2();
            return await CreateAsync(bild, fbController);
        }
        public static async Task<ArtikelBild> CreateAsync(ArtikelBild bild, FbController2 fbController)
        {
            string sql = @"INSERT INTO WK5_ARTIKELBILDER 
(ARBI_A_ARTINR,ARBI_A_IMGPFAD,ARBI_L_HAUPT)
VALUES
(@ARBI_A_ARTINR,@ARBI_A_IMGPFAD,@ARBI_L_HAUPT) RETURNING ARBI_N_NR;";


            fbController.AddParameter("@ARBI_A_ARTINR", bild.ARBI_A_ARTINR);
            fbController.AddParameter("@ARBI_A_IMGPFAD", bild.ARBI_A_IMGPFAD);
            fbController.AddParameter("@ARBI_L_HAUPT", bild.ARBI_L_HAUPT.ToFirebirdBool());


            var idObj = await fbController.FetchObjectAsync(sql);

            if (idObj is not null)
            {
                bild.ARBI_N_NR = Convert.ToInt32(idObj);
            }

            return bild;
        }

        public static async Task UpdateAsync(ArtikelBild bild)
        {
            string sql = @"UPDATE WK5_ARTIKELBILDER SET ARBI_A_ARTINR = @ARBI_A_ARTINR, ARBI_A_IMGPFAD = @ARBI_A_IMGPFAD, ARBI_L_HAUPT = @ARBI_L_HAUPT WHERE ARBI_N_NR = @ARBI_N_NR";
            using FbController2 fbController = new FbController2();
            fbController.AddParameter("@ARBI_A_ARTINR", bild.ARBI_A_ARTINR);
            fbController.AddParameter("@ARBI_A_IMGPFAD", bild.ARBI_A_IMGPFAD);
            fbController.AddParameter("@ARBI_N_NR", bild.ARBI_N_NR);
            fbController.AddParameter("@ARBI_L_HAUPT", bild.ARBI_L_HAUPT.ToFirebirdBool());

            await fbController.QueryAsync(sql);
        }

        public static async Task DeleteAsync(ArtikelBild bild)
        {
            string sql = "DELETE FROM WK5_ARTIKELBILDER WHERE ARBI_N_NR = @ARBI_N_NR";
            using FbController2 fbController = new FbController2();
            fbController.AddParameter("@ARBI_N_NR", bild.ARBI_N_NR);
            await fbController.QueryAsync(sql);

            try
            {
                File.Delete(bild.DriveImage);
            }
            catch (Exception ex)
            {
                Serilog.Log.Logger.Warning("Fehler beim löschen der ArtikelBild Datei ({DATEI}). Fehler: ", bild.DriveImage, ex);
            }
        }

        private static string? Download(string relativeOnlinePath)
        {
            string remoteImageLink = $"https://www.karley.de/image/{relativeOnlinePath}";


            string localFile = Path.Combine(LocalImageDirectory, relativeOnlinePath.TrimStart('/'));

            string? dirname = Path.GetDirectoryName(localFile);
            if (String.IsNullOrWhiteSpace(dirname))
            {
                return null;
            }

            var result = FileErweiterung.EnsureCreateDirectory(dirname);

            try
            {
                using WebClient client = new WebClient();

                client.DownloadFileAsync(new Uri(remoteImageLink), localFile);
            }
            catch (Exception ex)
            {
                Serilog.Log.Logger.Warning("Artikelbild {ARTIBILD} konnte nicht nach {LOCALBILD} heruntergeladen werden! Fehler: {EX}", remoteImageLink, localFile, ex);
                return null;
            }

            return Path.Combine("/assets/img/artikel", relativeOnlinePath).Replace("\\", "/");
        }

        #region Opencart
        private static async Task<string?> GetOpencartHauptBildAsync(string artikelnummer)
        {
            if (await GlobalConfig.GetConfigAsync(GlobalConfig.WK5_LIVESHOP_DISABLED_CONFIG_NAME) == "Y")
            {
                return null;
            }

            using MySqlController2 mySqlController = new MySqlController2();
            mySqlController.AddParameter("@ARTIKELNUMMER", artikelnummer);

            string? image;
            try
            {
                image = await mySqlController.FetchObjectAsync("SELECT image FROM product WHERE model = @ARTIKELNUMMER") as string ?? String.Empty;
            }
            catch (Exception ex)
            {
                Serilog.Log.Logger.Warning("Fehler beim abfragen des Hauptartikelbildes ({ARTI}) von Opencart. Fehler: {EX}", artikelnummer, ex);
                return null;
            }

            if (String.IsNullOrWhiteSpace(image))
            {
                return null;
            }

            return image;
        }

        private static async IAsyncEnumerable<string> GetOpencartSekundärBilderAsync(string artikelnummer)
        {
            using MySqlController2 mySqlController = new MySqlController2();
            mySqlController.AddParameter("@ARTIKELNUMMER", artikelnummer);

            DataTable? data = null;
            try
            {
                data = await mySqlController.SelectDataAsync("SELECT pi.image FROM product_image pi LEFT JOIN product p ON pi.product_id = p.product_id WHERE p.model = @ARTIKELNUMMER");
            }
            catch (Exception ex)
            {
                Serilog.Log.Logger.Warning("Fehler beim abfragen der Sekundärartikelbilder ({ARTI}) von Opencart. Fehler: {EX}", artikelnummer, ex);
            }

            if (data is not null)
            {
                foreach (DataRow row in data.Rows)
                {
                    if (row is not null)
                    {
                        string? image = row.Field<string>("image");
                        if (!String.IsNullOrWhiteSpace(image))
                        {
                            yield return image;
                        }
                    }
                }
            }
        }

        private static async Task<ArtikelBild?> OpencartBildSpeichernAsync(string? ocBild, string artikelnummer)
        {
            if (await GlobalConfig.GetConfigAsync(GlobalConfig.WK5_LIVESHOP_DISABLED_CONFIG_NAME) == "Y")
            {
                return null;
            }

            if (String.IsNullOrWhiteSpace(ocBild))
            {
                return null;
            }

            string? lokalOcBild = Download(ocBild);
            if (!String.IsNullOrWhiteSpace(lokalOcBild))
            {
                ArtikelBild artikelBild = new ArtikelBild()
                {
                    ARBI_A_ARTINR = artikelnummer,
                    ARBI_L_HAUPT = false,
                    ARBI_A_IMGPFAD = ocBild,
                };

                //await CreateAsync(artikelBild);
                return artikelBild;
            }
            else
            {
                return null;
            }
        }
        #endregion

        public static async Task<ArtikelBild?> GetHauptBildAsync(string artikelnummer)
        {
            List<ArtikelBild> lokalBilder = await GetArtikelBilderAsync(artikelnummer).ToListAsync();
            ArtikelBild? retVal = lokalBilder.Where(x => x.ARBI_L_HAUPT).FirstOrDefault();

            //if (await GlobalConfig.GetConfigAsync(GlobalConfig.WK5_LIVESHOP_DISABLED_CONFIG_NAME) != "Y")
            //{
            //    try
            //    {
            //        string? ocHauptBild = await GetOpencartHauptBildAsync(artikelnummer);
            //        if (!lokalBilder.Where(x => x.ARBI_A_IMGPFAD.Equals(ocHauptBild, StringComparison.OrdinalIgnoreCase)).Any())
            //        {
            //            ArtikelBild? hauptBild = await OpencartBildSpeichernAsync(ocHauptBild, artikelnummer);
            //            if (hauptBild is not null)
            //            {
            //                await CreateAsync(hauptBild);
            //            }
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        Log.Logger.Error($"#GetHauptBildAsync: {ex}");
            //    }


            //}

            return retVal;
        }
        public static async IAsyncEnumerable<ArtikelBild> GetSekundärBilderAsync(string artikelnummer)
        {
            List<ArtikelBild> lokalBilder = await GetArtikelBilderAsync(artikelnummer).Where(x => !x.ARBI_L_HAUPT).ToListAsync();
            //List<string> ocBilder = new List<string>();
            //if (await GlobalConfig.GetConfigAsync(GlobalConfig.WK5_LIVESHOP_DISABLED_CONFIG_NAME) != "Y")
            //{
            //    ocBilder = await GetOpencartSekundärBilderAsync(artikelnummer).ToListAsync();
            //}

            //List<ArtikelBild> bilder = lokalBilder;

            //foreach(string ocBild in ocBilder)
            //{
            //    if(!lokalBilder.Where(x => x.ARBI_A_IMGPFAD.Equals(ocBild, StringComparison.OrdinalIgnoreCase)).Any())
            //    {
            //        ArtikelBild? bild = await OpencartBildSpeichernAsync(ocBild, artikelnummer);
            //        if(bild is not null)
            //        {
            //            lokalBilder.Add(await CreateAsync(bild));
            //        }
            //    }
            //}

            foreach (ArtikelBild bild in lokalBilder)
            {
                yield return bild;
            }
        }

        public static async IAsyncEnumerable<ArtikelBild> GetBilderAsync(string artikelnummer)
        {
            ArtikelBild? haupt = await GetHauptBildAsync(artikelnummer);
            if (haupt is not null)
            {
                yield return haupt;
            }

            await foreach (ArtikelBild bild in GetSekundärBilderAsync(artikelnummer))
            {
                yield return bild;
            }
        }

        public static async IAsyncEnumerable<ArtikelBild> GetAlleBilderAsync()
        {
            using FbController2 fbController = new FbController2();            

            DataTable data = await fbController.SelectDataAsync("SELECT * FROM WK5_ARTIKELBILDER");
            foreach (DataRow row in data.Rows)
            {
                if (row is not null)
                {
                    yield return ObjectErweiterung.DataRowZuObjekt(new ArtikelBild(), row);
                }
            }
        }

        public static async Task<ArtikelBild?> GetArtikelbildByIdAsync(int bildId, FbController2 fbController)
        {
            fbController.AddParameter("@ARBI_N_NR", bildId);
            DataRow? row = await fbController.SelectRowAsync("SELECT * FROM WK5_ARTIKELBILDER WHERE ARBI_N_NR = @ARBI_N_NR");

            return row is null ? null : ObjectErweiterung.DataRowZuObjekt(new ArtikelBild(), row);
        }
        public static async Task<ArtikelBild?> GetArtikelbildByImagePfadAsync(string imagePfad, FbController2 fbController)
        {
            fbController.AddParameter("@ARBI_A_IMGPFAD", imagePfad);
            DataRow? row = await fbController.SelectRowAsync("SELECT * FROM WK5_ARTIKELBILDER WHERE ARBI_A_IMGPFAD = @ARBI_A_IMGPFAD");

            return row is null ? null : ObjectErweiterung.DataRowZuObjekt(new ArtikelBild(), row);
        }

    }
}
