using APT.BaseData.Domain.Entities.FM;
using APT.BaseData.Domain.Enums;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TokenRequest = APT.Utility.TokenRequest;
using APT.Infrastructure.Core;
using IdentityModel.Client;
using APT.BaseData.Domain.Entities;
using APT.BaseData.Domain.Entities.OP;
using APT.Infrastructure.Api;
namespace APT.OP.WebApi.Controllers.Api
{
    [Route("api/OP/Token")]
    public class TokenController : Controller
    {
        [HttpPost, Route("Gen")]
        public async Task<IActionResult> Gen([FromBody] TokenRequest request)
        {
            try
            {
                if (request.Grant_type == (int)PFGrantTypeEnum.账号密码)
                {
                    var client = new System.Net.Http.HttpClient();
                    ///
                    //var disco = await client.GetDiscoveryDocumentAsync(ConfigurationManager.AppSettings["IdentityServer"]);
                    //if (disco.IsError)
                    //{
                    //    Console.WriteLine(disco.Error);
                    //    return BadRequest(new { error = disco.Error, error_description = "验证服务器无法连接" });
                    //}
                    var user = this.GetUser(request);
                    if (user == null)
                        return BadRequest(new { error = "error Account ", error_description = "用户不存在或者密码错误" }); ;
                    // request access token
                    var scope = "offline_access oEnergyPF  oEnergyDD oEnergyLG oEnergyOP oEnergyFM oEnergyBD oEnergyHM";

                    var dic = new Dictionary<string, string>();
                    dic.Add("UserId", user.ID.ToString());
                    var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
                    {
                        //Address = disco.TokenEndpoint,
                        Address = ConfigurationManager.AppSettings["IdentityServer"] + "connect/token",
                        ClientId = ConfigurationManager.AppSettings["ClientId"],
                        ClientSecret = ConfigurationManager.AppSettings["SecurityKey"],
                        Scope = scope,
                        UserName = "55274652@qq.com",
                        Password = "Aa123!",

                    });

                    if (tokenResponse.IsError)
                    {
                        return BadRequest(new { error = tokenResponse.Error, error_description = tokenResponse.Error ?? tokenResponse.ErrorDescription }); ;
                    }

                    return Ok(new
                    {
                        access_token = tokenResponse.AccessToken,
                        token_type = tokenResponse.TokenType,
                        expiresIn = tokenResponse.ExpiresIn,
                        userid = user.ID,
                        refreshToken = tokenResponse.RefreshToken,
                    });
                }
                else if (request.Grant_type == (int)PFGrantTypeEnum.客户端)
                {
                    var client = new System.Net.Http.HttpClient();

                    var dataChanel = GetDataChanel(request);
                    var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
                    {
                        Address = ConfigurationManager.AppSettings["IdentityServer"] + "connect/token",
                        ClientId = request.ClientId,
                        ClientSecret = request.ClinetSecret,
                        Scope = GetScopes(request),
                    });

                    if (tokenResponse.IsError)
                    {
                        return BadRequest(new { error = tokenResponse.Error, error_description = tokenResponse.Error ?? tokenResponse.ErrorDescription }); ;
                    }
                    T_OP_TENANT tenantCode = null;
                    if (dataChanel.TENANT_ID != null)
                        tenantCode = GetTenantCode(dataChanel.TENANT_ID ?? Guid.Empty);
                    return Ok(new
                    {
                        access_token = tokenResponse.AccessToken,
                        token_type = tokenResponse.TokenType,
                        refreshToken = tokenResponse.RefreshToken,
                        expiresIn = tokenResponse.ExpiresIn,
                        dataChanel = dataChanel,
                        tenantCode = tenantCode.CODE,
                        OrgId = tenantCode.ID
                    }); ;
                }
                if (request.Grant_type == (int)PFGrantTypeEnum.Refresh)
                {
                    var client = new System.Net.Http.HttpClient();

                    var tokenResponse = await client.RequestRefreshTokenAsync(new RefreshTokenRequest
                    {
                        //Address = disco.TokenEndpoint,
                        Address = ConfigurationManager.AppSettings["IdentityServer"] + "connect/token",
                        ClientId = ConfigurationManager.AppSettings["ClientId"],
                        ClientSecret = ConfigurationManager.AppSettings["SecurityKey"],
                        RefreshToken = request.RefreshToken
                    });

                    if (tokenResponse.IsError)
                    {
                        return BadRequest(new { error = tokenResponse.Error, error_description = tokenResponse.Error ?? tokenResponse.ErrorDescription }); ;
                    }

                    return Ok(new
                    {
                        access_token = tokenResponse.AccessToken,
                        token_type = tokenResponse.TokenType,
                        refreshToken = tokenResponse.RefreshToken,
                        expiresIn = tokenResponse.ExpiresIn,
                    });
                }
                return BadRequest(new { error = "grant_type_error", error_description = "grant_type_error" });
            }
            catch (Exception ex)
            {

                return BadRequest(new { error = "excetion", error_description = ex.Message });
            }


        }
        private T_OP_USER GetUser(TokenRequest request)
        {
            var commonService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<ICommonService>();
            if (string.IsNullOrEmpty(request.UserName.Trim()))
                return null;
            var loginUser = commonService.GetEntity<T_OP_USER>(i => (i.CODE.ToUpper() == request.UserName.ToUpper()
                || i.PHONE == request.UserName) && i.PASSWORD.ToUpper() == request.Password.ToUpper());

            return loginUser;
        }

        private string GetScopes(TokenRequest request)
        {
            var sopestr = "";
            var commonService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<ICommonService>();
            if (string.IsNullOrEmpty(request.ClientId.Trim()))
                return null;

            var scopes = commonService.GetEntities<T_PF_CLIENT_SCOPES>(i => i.Nav_DataChanel.APP_ID == request.ClientId, "Nav_Scope").ToList();
            if (scopes.Any())
                foreach (var s in scopes)
                {
                    sopestr += s.Nav_Scope.NAME + " ";
                }
            sopestr = sopestr.Trim();
            return sopestr;
        }

        private T_PF_DATA_CHANNEL GetDataChanel(TokenRequest request)
        {
            var sopestr = "";
            var commonService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<ICommonService>();
            if (string.IsNullOrEmpty(request.ClientId.Trim()))
                return null;
            var dataChanel = commonService.GetEntity<T_PF_DATA_CHANNEL>(i => i.APP_ID == request.ClientId && i.SECURITY_KEY == request.ClinetSecret
            && i.ENABLE_STATUS == (int)FMEnableStatusEnum.启用, "Nav_DataFrequency");
            if (dataChanel == null)
            {
                LibMessageUtils.ThrowError("020003", request.ClientId);
            }
            return dataChanel;
        }
        private T_OP_TENANT GetTenantCode(Guid id)
        {
            var commonService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<ICommonService>();
            var filter = new BaseFilter();
            filter.IgnoreOrgRule = true;
            filter.SelectField = new string[] { "CODE", "ID" };
            var tenant = commonService.GetEntity<T_OP_TENANT>(i => i.ID == id, filter);
            if (tenant == null)
            {
                LibMessageUtils.ThrowError("020026");
            }
            return tenant;
        }

    }
}
