using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using wispro.sp.share.webViewObject;
using wispro.sp.web.Auth;
using wispro.sp.web.Utils;

namespace wispro.sp.web.Services
{
    public interface IHttpService
    {
        Task<T> Get<T>(string uri);
        Task<T> Post<T>(string uri, object value);

        Task<byte[]> Post(string uri, object value);
    }

    public class HttpService:IHttpService
    {
        private HttpClient _httpClient;
        private NavigationManager _navigationManager;
        private ILocalStorageService _localStorageService;
        private IConfiguration _configuration;
        //private IAuthService _authService;
        private AuthenticationStateProvider authenticationStateProvider;

        public HttpService(
            HttpClient httpClient,
            NavigationManager navigationManager,
            ILocalStorageService localStorageService,
            IConfiguration configuration,
            AuthenticationStateProvider authService
        )
        {
            _httpClient = httpClient;
            _navigationManager = navigationManager;
            _localStorageService = localStorageService;
            _configuration = configuration;
            authenticationStateProvider = authService;
        }

        public async Task<T> Get<T>(string uri)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, $"{_configuration.GetValue<string>("APIUrl")}{uri}");
            return await sendRequest<T>(request);
        }

        public async Task<T> Post<T>(string uri, object value)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration.GetValue<string>("APIUrl")}{uri}");
            request.Content = new StringContent(JsonSerializer.Serialize(value), Encoding.UTF8, "application/json");
            return await sendRequest<T>(request);
        }

        public async Task<byte[]> Post(string uri, object value)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration.GetValue<string>("APIUrl")}{uri}");
            //request.Headers.Add("Content-Type", "application/json");
            request.Content = new StringContent(JsonSerializer.Serialize(value), Encoding.UTF8, "application/json");
            var data =await snedRequestNotReturn(request);

            return data;

        }

        private async Task<byte[]> snedRequestNotReturn(HttpRequestMessage request)
        {
            // add jwt auth header if user is logged in and request is to the api url
            try
            {
                var user = await _localStorageService.GetItemAsync<userToken>("authToken");
                var isApiUrl = !request.RequestUri.IsAbsoluteUri;

                if (user != null) // && isApiUrl)
                {
                    //request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", user.Token);

                    //將token取出轉為claim
                    var claims = JwtParser.ParseClaimsFromJwt(user.Token);

                    //在每次request的header中帶入bearer token
                    _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", user.Token);
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.ToString());
            }

            using HttpResponseMessage response = await _httpClient.SendAsync(request);

            // auto logout on 401 response
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                _httpClient.DefaultRequestHeaders.Authorization = null;
                await _localStorageService.RemoveItemAsync("authToken");
                ((JwtAuthenticationStateProvider)authenticationStateProvider).NotifyUserLogOut();
            }

            // throw exception on error response
            if (!response.IsSuccessStatusCode)
            {
                //var error = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
                throw new Exception("Error");
            }

            return await response.Content.ReadAsByteArrayAsync();
        }

        private async Task<T> sendRequest<T>(HttpRequestMessage request)
        {
            // add jwt auth header if user is logged in and request is to the api url
            try
            {
                var user = await _localStorageService.GetItemAsync<userToken>("authToken");
                var isApiUrl = !request.RequestUri.IsAbsoluteUri;

                if (user != null) // && isApiUrl)
                {
                    //request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", user.Token);

                    //將token取出轉為claim
                    var claims = JwtParser.ParseClaimsFromJwt(user.Token);

                    //在每次request的header中帶入bearer token
                    _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", user.Token);
                }
            }
            catch(Exception ex) {
                //Console.WriteLine(ex.ToString());
            }

            using HttpResponseMessage response = await _httpClient.SendAsync(request);

            // auto logout on 401 response
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                _httpClient.DefaultRequestHeaders.Authorization = null;
                await _localStorageService.RemoveItemAsync("authToken");
                ((JwtAuthenticationStateProvider)authenticationStateProvider).NotifyUserLogOut();
                return default;
            }

            // throw exception on error response
            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadFromJsonAsync<string>();
                throw new Exception(error);
            }
            var retData =await response.Content.ReadFromJsonAsync<T>();
            
            return retData;
        }
    }
}
