namespace Hims.Infrastructure.Helpers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Domain.Configurations;
    using Domain.Helpers;
    using Hims.Domain.Entities;
    using IdentityModel.Client;
    using Shared.Library.Enums;

    /// <inheritdoc />
    public class AuthHelper : IAuthHelper
    {
        /// <summary>
        /// The identity server configuration.
        /// </summary>
        private readonly IIdentityServerConfiguration identityServerConfiguration;

        /// <summary>
        /// Initializes a new instance of the <see cref="AuthHelper"/> class.
        /// </summary>
        /// <param name="identityServerConfiguration">
        /// The identity server configuration.
        /// </param>
        public AuthHelper(IIdentityServerConfiguration identityServerConfiguration) => this.identityServerConfiguration = identityServerConfiguration;

        /// <inheritdoc />
        public Task<DiscoveryDocumentResponse> GetIdentityServerAsync()
        {
            var client = new HttpClient();
            return client.GetDiscoveryDocumentAsync(this.identityServerConfiguration.Authority);
        }

        /// <inheritdoc />
        public Task<TokenResponse> SignInAsync(DiscoveryDocumentResponse identityServer, string userName, string password, IEnumerable<AccountType> accountTypes, int? accountId)
        {
            var client = new HttpClient();
            return client.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                Address = identityServer.TokenEndpoint,
                ClientId = this.identityServerConfiguration.ClientId,
                ClientSecret = this.identityServerConfiguration.ClientSecret,
                UserName = accountId == null ? userName + "!!" + string.Join(",", accountTypes.Select(m => (int)m)) : "@@" + accountId,
                Password = accountId == null ? password : "@@" + accountId,
                Scope = $"{this.identityServerConfiguration.ApiName} openid offline_access role"
            });
        }

        /// <inheritdoc />
        public Task<TokenResponse> SignInAltAsync(DiscoveryDocumentResponse identityServer, string userName, string password, List<int> roles, int? accountId)
        {
            try
            {
                var client = new HttpClient();
                return client.RequestPasswordTokenAsync(new PasswordTokenRequest
                {
                    Address = identityServer.TokenEndpoint,
                    ClientId = this.identityServerConfiguration.ClientId,
                    ClientSecret = this.identityServerConfiguration.ClientSecret,
                    UserName = accountId == null ? userName: "@@" + accountId,
                    Password = accountId == null ? password : "@@" + accountId,
                    Scope = $"{this.identityServerConfiguration.ApiName} openid offline_access role"
                });
            }
            catch (Exception ex)
            {
                ex.Message.ToString();
            }
            return null;
        }

        /// <inheritdoc />
        public Task<TokenResponse> PatientSignInAsync(DiscoveryDocumentResponse identityServer, string userName, string password, int? accountId)
        {
            try
            {
                var client = new HttpClient();
                return client.RequestPasswordTokenAsync(new PasswordTokenRequest
                {
                    Address = identityServer.TokenEndpoint,
                    ClientId = this.identityServerConfiguration.ClientId,
                    ClientSecret = this.identityServerConfiguration.ClientSecret,
                    UserName = accountId != null ? userName + "!!" + accountId : "@@" + accountId,
                    Password = accountId != null ? password : "@@" + accountId,
                    Scope = $"{this.identityServerConfiguration.ApiName} openid offline_access role"
                });
            }
            catch (Exception ex)
            {
                ex.Message.ToString();
            }
            return null;
        }
        /// <inheritdoc />
        public Task<TokenResponse> RefreshSignInAsync(DiscoveryDocumentResponse identityServer, string refreshToken)
        {
            var client = new HttpClient();
            return client.RequestRefreshTokenAsync(new RefreshTokenRequest
            {
                Address = identityServer.TokenEndpoint,
                ClientId = this.identityServerConfiguration.ClientId,
                ClientSecret = this.identityServerConfiguration.ClientSecret,
                RefreshToken = refreshToken
            });
        }

        /// <inheritdoc />
        public Task<UserInfoResponse> FetchUserInfoAsync(DiscoveryDocumentResponse identityServer, string accessToken)
        {
            var client = new HttpClient();
            return client.GetUserInfoAsync(new UserInfoRequest
            {
                Address = identityServer.UserInfoEndpoint,
                Token = accessToken
            });
        }
    }
}