using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.JSInterop;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text;
using TIAM.Entities.TransferDestinations;
using TIAM.Entities.Users;
using TIAMWebApp.Shared.Application.Interfaces;
using TIAMWebApp.Shared.Application.Models;
using TIAMWebApp.Shared.Application.Models.ClientSide;
using TIAMWebApp.Shared.Application.Models.PageModels;
using TIAMWebApp.Shared.Application.Utility;
using AyCode.Interfaces.StorageHandlers;
using AyCode.Core.Logger;
using TIAM.Models.Dtos.Users;


namespace TIAMWebApp.Client.Services
{
    public class UserDataServiceWeb : IUserDataService
    {
        private readonly HttpClient http;
        private readonly ISecureStorageHandler secureStorageHandler;
        private readonly IJSRuntime jsRuntime;
        private readonly LogToBrowserConsole logToBrowserConsole;
        private readonly IServiceProviderDataService serviceProviderDataService;
        public Dictionary<int, string> userRoleTypes { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public UserDataServiceWeb(HttpClient http, ISecureStorageHandler secureStorageHandler, IJSRuntime jSRuntime, IServiceProviderDataService serviceProviderDataService)
        {
            this.http = http;
            this.secureStorageHandler = secureStorageHandler;
            this.jsRuntime = jSRuntime;
            this.logToBrowserConsole = new LogToBrowserConsole(jsRuntime);
            this.serviceProviderDataService = serviceProviderDataService;
        }




        public async Task<UserSessionModel> IsLoggedInAsync(Guid id)
        {
            //api call to get user
            var userModelDto = await GetUserByIdAsync(id);

            if (userModelDto != null)
            {
                //get user's properties
                var hasProperties = await serviceProviderDataService.GetPropertiesByOwnerIdAsync(userModelDto.Id);

                if (hasProperties != null)
                    logToBrowserConsole.LogToBC($"{hasProperties.Count} properties found");

                //create user session model
                var user = new UserSessionModel(userModelDto.Id, UserType.User, userModelDto.Profile?.Name, hasProperties, 1);
                return user;
            }
            else
            {

                return null;
            }

        }

        public async Task<string> TestUserApi(int Param)
        {
            var url = $"{Setting.BaseUrl}/{APIUrls.UserTest}";


            var response = await http.PostAsJsonAsync(url, Param);
            var result = await response.Content.ReadAsStringAsync();
            return result;
        }

        public async Task<string> AuthenticateUser(LoginModel loginModel)
        {
            string result = string.Empty;
            var url = $"{Setting.BaseUrl}/{APIUrls.AuthenticateUser}";

            var response = await http.PostAsJsonAsync(url, loginModel);

            //try
            //{
            //    Logger.Detail("Login started: " + "Email: " + loginModel.Email + ", Password: " + loginModel.Password);
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine(ex);
            //}

            if (response.IsSuccessStatusCode)
            {
                result = await response.Content.ReadAsStringAsync();
            }
            else
            {
                result = await response.Content.ReadAsStringAsync();
            }

            //result = await response.Content.ReadAsStringAsync();            
            return result;

        }

        public async Task<(bool isSuccess, string ErrorMessage)> CreateUser(RegistrationModel regModel)
        {

            bool isSuccess = true;
            string result = string.Empty;
            var url = $"{Setting.BaseUrl}/{APIUrls.CreateUser}";
            logToBrowserConsole.LogToBC("CreateUser url: " + url);
            var response = await http.PostAsJsonAsync(url, regModel);
            result = await response.Content.ReadAsStringAsync();
            /*if (response.IsSuccessStatusCode)
            {
                isSuccess = true;
                result = await response.Content.ReadAsStringAsync();
            }
            else
            {
                isSuccess = false;
                result = await response.Content.ReadAsStringAsync();
            }*/


            return (isSuccess, result);
        }

        public async Task<IEnumerable<UserModelDto>?> GetUsersAsync()
        {
            return await http.GetFromJsonAsync<IEnumerable<UserModelDto>>(APIUrls.GetUsers);
        }

        public async Task<UserModelDto?> GetUserByEmailAsync(string email)
        {
            var url = $"{Setting.BaseUrl}/{APIUrls.GetUserByEmail}";
            return await http.GetFromJsonAsync<UserModelDto?>(url);
        }

        public async Task<UserModelDto?> GetUserByIdAsync(Guid id)
        {
            var url = $"{Setting.BaseUrl}/{APIUrls.GetUserById}";
            logToBrowserConsole.LogToBC("GetUserByIdAsync url: " + url + ", " + id.ToString());

            var response = await http.PostAsJsonAsync(url, id);
            var result = await response.Content.ReadAsStringAsync();
            var user = JsonConvert.DeserializeObject<UserModelDto>(result);

            return user;
        }

        public async Task<bool> RefreshToken()
        {
            logToBrowserConsole.LogToBC("RefreshToken() called");
            bool isTokenRefreshed = false;

            var url = $"{Setting.BaseUrl}/{APIUrls.RefreshToken}";
            //var url = APIUrls.RefreshToken;                

            var serializedStr = JsonConvert.SerializeObject(new AuthenticateRequestAndResponse
            {
                RefreshToken = Setting.UserBasicDetails.RefreshToken,
                AccessToken = Setting.UserBasicDetails.AccessToken
            });

            try
            {
                logToBrowserConsole.LogToBC("Refreshtoken url: " + url);
                var response = await http.PostAsync(url, new StringContent(serializedStr, Encoding.UTF8, "application/json"));
                if (response.IsSuccessStatusCode)
                {
                    string contentStr = await response.Content.ReadAsStringAsync();
                    var mainResponse = JsonConvert.DeserializeObject<MainResponse>(contentStr);
                    if (mainResponse.IsSuccess)
                    {
                        var tokenDetails = JsonConvert.DeserializeObject<AuthenticateRequestAndResponse>(mainResponse.Content.ToString());
                        Setting.UserBasicDetails.AccessToken = tokenDetails.AccessToken;
                        Setting.UserBasicDetails.RefreshToken = tokenDetails.RefreshToken;

                        string userDetailsStr = JsonConvert.SerializeObject(Setting.UserBasicDetails);
                        await secureStorageHandler.SaveToSecureStorageAsync(nameof(Setting.UserBasicDetails), userDetailsStr);
                        isTokenRefreshed = true;
                    }
                }
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                logToBrowserConsole.LogToBC("Refreshtoken exception: " + ex.ToString());
            }



            return isTokenRefreshed;
        }


        /*public Task<Dictionary<int, string>> GetUserRolesAsync(UserModel userModel)
        {
            //TODO: finish this
            //get the userModel's roles
            int role = userModel.UserRoles;

            foreach (var roleType in roleTypes)
            {
                if ((role & roleType.Id) == roleType.Id)
                {

                    //add the role to the dictionary
                    userRoleTypes.Add(roleType.Id, roleType.RoleName);

                }
            }
            return Task.FromResult(userRoleTypes);

        }*/
    }
}

