using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Web;
using LaneFlowReport.Options;
using Microsoft.Extensions.Options;

namespace LaneFlowReport.Auth {
    public class ParkingAuthProvider {
        private readonly IOptions<OauthOption> _oauthOption;
        private readonly IHttpClientFactory _httpClientFactory;


        public ParkingAuthProvider(IOptions<OauthOption> oauthOption, IHttpClientFactory httpClientFactory) {
            _oauthOption = oauthOption;
            _httpClientFactory = httpClientFactory;
        }

        public const string Name = "Parking";
        public async Task<ExternalUserInfoModel> GetUserInfo(string accessCode) {
            var providerInfo = new {
                _oauthOption.Value.ClientUrl,
                _oauthOption.Value.ClientSecret
            };
            var mode = accessCode.Split(";")?[0];
            var key = accessCode.Split(";")?[1];
            string url;
            object param;
            if (mode == "line") {
                param = new {
                    accessToken = providerInfo.ClientSecret,
                    loginProvider = mode,
                    providerKey = key,
                    roleName = "",
                };
                url = $"{providerInfo.ClientUrl}ExternalRoleOAuth";
            }
            else {
                param = new {
                    userId = key,
                    accessToken = providerInfo.ClientSecret
                };
                url = $"{providerInfo.ClientUrl}ExternalOAuth";
            }
            var httpClient = _httpClientFactory.CreateClient();
            var query = GetQueryString(param);
            var content = new StringContent(query, Encoding.UTF8, "application/x-www-form-urlencoded");
            var response = await httpClient.PostAsync(url, content);
            if (response.StatusCode != HttpStatusCode.OK) {
                throw new Exception("Parking Login Error");
            }
            var responseString = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<AjaxResponse<ExternalUserInfoModel>>(responseString);
            if (result?.Result == null) {
                throw new Exception("User not exist");
            }

            return new ExternalUserInfoModel {
                FullName = result.Result.FullName,
                EmailAddress = result.Result.EmailAddress,
                PhotoUrl = result.Result.PhotoUrl,
                UserName = result.Result.UserName
            };

        }
        private string GetQueryString(object obj) {
            var properties = from p in obj.GetType().GetProperties()
                             where p.GetValue(obj, null) != null
                             select p.Name + "=" + HttpUtility.UrlEncode(p.GetValue(obj, null).ToString());

            return String.Join("&", properties.ToArray());
        }


    }
    public class ExternalUserInfoModel
    {
        [JsonPropertyName("tenantId")]
        public int TenantId { get; set; }

        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("userName")]
        public string UserName { get; set; }

        [JsonPropertyName("fullName")]
        public string FullName { get; set; }

        [JsonPropertyName("photoUrl")]
        public string PhotoUrl { get; set; }

        [JsonPropertyName("emailAddress")]
        public string EmailAddress { get; set; }
    }

    public class AjaxResponse<T>
    {
        [JsonPropertyName("result")]
        public T Result { get; set; }

        [JsonPropertyName("targetUrl")]
        public object TargetUrl { get; set; }

        [JsonPropertyName("success")]
        public bool Success { get; set; }

        [JsonPropertyName("error")]
        public object Error { get; set; }

        [JsonPropertyName("unAuthorizedRequest")]
        public bool UnAuthorizedRequest { get; set; }

        [JsonPropertyName("__abp")]
        public bool Abp { get; set; }
    }

}
