using DevExpress.Drawing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using QRCoder;
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.Text.Json;
using TIAM.Database.DataLayers.Admins;
//using TIAM.Database.DataLayers.ServiceProviders;
using TIAM.Entities.Permissions;
using TIAM.Entities.Products;
using TIAM.Entities.ServiceProviders;
using TIAM.Entities.Users;
using TIAMWebApp.Shared.Application.Models;
using Product = TIAM.Entities.Products.Product;

namespace TIAMWebApp.Server.Controllers
{
    [Authorize]
    [ApiController]
    [Route("api/v1/[controller]")]
    public class ServiceProviderAPIController : ControllerBase
    {
        private AdminDal _adminDal;

        private readonly ILogger<ServiceProviderAPIController> _logger;

        public ServiceProviderAPIController(ILogger<ServiceProviderAPIController> logger, AdminDal adminDal)
        {
            _logger = logger;
            _adminDal = adminDal;
        }

        //15.
        [HttpPost]
        [Route(APIUrls.CreateServiceProviderRouteName)]
        [Tags("In-Progress", "ServiceProvider")]
        [EndpointSummary("Create assigned user")]
        public async Task<IActionResult> CreateServiceProvider([FromBody] ServiceProviderModel serializedServiceProviderModel)
        {
            Console.WriteLine("CreateUser called");
            if (serializedServiceProviderModel == null)
            {
                return BadRequest("SerializedLoginModel is required");
            }
            else
            {
                //ServiceProviderModel? serviceProvider = JObject.Parse(serializedServiceProviderModel.GetRawText()).ToObject<ServiceProviderModel>();
                var serviceProvider = serializedServiceProviderModel;


                if (serviceProvider != null)
                {
                    //add userModel to users array
                    //Array.Resize(ref users, users.Length + 1);
                    //users[users.Length - 1] = new UserModel(user.Email, user.PhoneNumber, user.Password);

                    var id = Guid.NewGuid();
                    var name = serializedServiceProviderModel.Name;
                    var ownerId = serializedServiceProviderModel.OwnerId;



                    if (name is null || ownerId == Guid.Empty)
                    {
                        return BadRequest("Invalid request");
                    }
                    else
                    {

                        Console.WriteLine($"ServiceProvider to be created: {id}, {name}, {ownerId}");

                        await _adminDal.CreateServiceProviderAsync(new TiamServiceProvider(id, name, ownerId, Guid.NewGuid()));
                    }
                }

                return Ok("yes");
            }
        }

        //16.
        [AllowAnonymous]
        [HttpGet]
        [Route(APIUrls.GetServiceProvidersRouteName)]
        public Task<List<TiamServiceProvider>> GetServiceProviders()
        {
            //var users = await _serviceProviderDal.Ctx.Users.ToListAsync();//.GetUsersAsync();
            //return users;
            return _adminDal.GetServiceProvidersAsync();
        }

        //18.
        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.GetServiceProviderByIdRouteName)]
        public async Task<TiamServiceProvider?> GetServiceProviderById([FromBody] Guid id)
        {
            Console.WriteLine($"GetServiceProviderById called with id: {id}");

            return await _adminDal.GetServiceProviderByIdAsync(id);
        }

        //17.
        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.GetServiceProvidersByOwnerIdRouteName)]
        [Tags("Finished", "ServiceProvider")]
        public async Task<Dictionary<Guid, string>> GetServiceProvidersByOwnerId([FromBody] Guid ownerId)
        {
            Console.WriteLine($"GetServiceProvidersByOwnerId called with ownerId: {ownerId}");

            var serviceProviders = await _adminDal.GetServiceProvidersAsync();

            //return serviceProviders.Where(x => x.OwnerId == ownerId).ToList();
            var myServiceproviders = serviceProviders.Where(x => x.OwnerId == ownerId).ToDictionary(x => x.Id, x => x.Name);
            //put TiamServiceProvider id and name into a dictionary          

            return myServiceproviders;
        }

        //22.
        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.CreateUserProductMappingRouteName)]        
        [Tags("Finished", "ServiceProvider")]
        [EndpointSummary("Create assigned user to product")]
        public async Task<IActionResult> CreateUserProductMapping(CreateUserProductMappingModel createUserProductMappingModel)
        {
            if(createUserProductMappingModel.ContextId == Guid.Empty || createUserProductMappingModel.UserId == Guid.Empty)
            {
                return BadRequest("Invalid request");
            }
            else
            {
                Console.WriteLine($"CreateUserProductMappings called with ownerId: {createUserProductMappingModel.ContextId}, {createUserProductMappingModel.ContextId}");

                var userProductMapping = new UserProductMapping(createUserProductMappingModel.ContextId, createUserProductMappingModel.ContextId);

                var result = await _adminDal.AddUserProductMappingAsync(userProductMapping);

                return Ok(result);
            }
        }

        //23.
        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.GetUserProductMappingsForProductRouteName)]        
        public async Task<Dictionary<Guid, string>> GetUserProductMappingsForProduct(Guid serviceProviderId)
        {
            Console.WriteLine($"GetUserProductMappingsForServiceProvider called with serviceProviderId: {serviceProviderId}");

            var userProductMappingDictionary = new Dictionary<Guid, string>();

            var serviceProviders = await _adminDal.GetServiceProvidersAsync();

            var myServiceproviders = serviceProviders.Where(x => x.Id == serviceProviderId).ToDictionary(x => x.Id, x => x.Name);
            //put serviceprovider id and name into a dictionary            

            return myServiceproviders;
        }

        [HttpPost]
        [Route(APIUrls.AddProductRouteName)]
        [Tags("In-Progress", "Product")]
        public async Task<IActionResult> AddProduct([FromBody] Product product)
        {
            Console.WriteLine("AddProduct called");
            if (product == null)
            {
                return BadRequest("Product is required");
            }
            else
            {
                var result = _adminDal.AddProduct(product);
                return Ok(result);
            }
        }

        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.GetQRCodeByProductIdRouteName)]
        [Tags("In-Progress", "Product")]
        public async Task<IActionResult> GetQRCodeByProductId([FromBody] Guid productId)
        {
            Console.WriteLine("GetQRCode called");
            if (productId == Guid.Empty)
            {
                return BadRequest("Product is required");
            }
            else
            {
                //var result = _serviceProviderDal.GetQRCodeAsync(productId);

                var qrGenerator = new QRCodeGenerator();
                var qrCodeData = qrGenerator.CreateQrCode($"https://touriam.com/{productId}", QRCodeGenerator.ECCLevel.Q);
                var qrCode = new QRCode(qrCodeData);
                //Bitmap qrCodeImage = qrCode.GetGraphic(20);
                var rootpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "assets");
                var qrCodeImage = qrCode.GetGraphic(20, Color.DarkMagenta, Color.White, (Bitmap)Bitmap.FromFile(rootpath + "/myimage.png"));
                Console.WriteLine($"qrCodeLogo: {rootpath}/myimage.png");
                var ms = new MemoryStream();
                qrCodeImage.Save(ms, ImageFormat.Jpeg);
                var byteImage = ms.ToArray();

                var sigBase64 = Convert.ToBase64String(byteImage); // Get Base64
                
                return Ok(sigBase64);
            }
        }

        [AllowAnonymous]
        [HttpPost]
        [Route(APIUrls.GetProductsByServiceProviderIdRouteName)]
        [Tags("In-Progress", "Product")]
        public IActionResult GetProductsByServiceProviderId([FromBody] Guid serviceProviderId)
        {
            Console.WriteLine($"GetProductsByServiceProviderId called with serviceProviderId: {serviceProviderId}");

            if (serviceProviderId == Guid.Empty)
            {
                return BadRequest("Invalid request");
            }
            else
            {
                var products = _adminDal.GetProductsJsonByServiceProviderId(serviceProviderId);
                if (products != null)
                {                    
                    return Ok(products);
                }
                else
                {
                    //some Iactionresult that explains that there were errors
                    return StatusCode(500);

                }
                
            }

        }
    }
}