using AlibabaCloud.SDK.Sts20150401;
using Amazon.SecurityToken;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Serilog;
using System.Globalization;
using System.Text;
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;

namespace IRaCIS.Api.Controllers
{
    /// <summary>
    /// 医生基本信息 、工作信息  专业信息、审核状态
    /// </summary>
    [ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
    public class ExtraController([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
            [FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,

            [FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService) : ControllerBase
    {


        /// <summary>
        ///  获取医生详情 
        /// </summary>
        /// <param name="attachmentService"></param>
        /// <param name="_doctorService"></param>
        /// <param name="_educationService"></param>
        /// <param name="_trialExperienceService"></param>
        /// <param name="_researchPublicationService"></param>
        /// <param name="_vacationService"></param>
        /// <param name="doctorId"></param>
        /// <returns></returns>
        [HttpPost, Route("doctor/getDetail")]

        public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail(GetDoctorDetailInDto inDto)
        {
            var education = await _educationService.GetEducation(inDto.doctorId);

            var sowList = _doctorService.GetDoctorSowList(inDto.doctorId);
            var ackSowList = _doctorService.GetDoctorAckSowList(inDto.doctorId);

            var doctorDetail = new DoctorDetailDTO
            {
                AuditView = await _doctorService.GetAuditState(inDto.doctorId),
                BasicInfoView = await _doctorService.GetBasicInfo(inDto.doctorId),
                EmploymentView = await _doctorService.GetEmploymentInfo(inDto.doctorId),
                AttachmentList = await attachmentService.GetAttachments(inDto.doctorId),
                SummarizeInfo = await _doctorService.GetSummarizeInfo(new GetSummarizeInfoInDto()
                {
                    DoctorId = inDto.doctorId,
                    TrialId = inDto.TrialId
                }),
                PaymentModeInfo = await _doctorService.GetPaymentMode(inDto.doctorId),
                EducationList = education.EducationList,
                PostgraduateList = education.PostgraduateList,

                TrialExperienceView = await _trialExperienceService.GetTrialExperience(new TrialExperienceModelIndto()
                {
                    DoctorId = inDto.doctorId,
                    TrialId = inDto.TrialId
                }),
                ResearchPublicationView = await _researchPublicationService.GetResearchPublication(inDto.doctorId),

                SpecialtyView = await _doctorService.GetSpecialtyInfo(inDto.doctorId),
                InHoliday = (await _vacationService.OnVacation(inDto.doctorId)).IsSuccess,
                IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(inDto.doctorId),
                SowList = sowList,
                AckSowList = ackSowList
            };

            return ResponseOutput.Ok(doctorDetail);
        }







        [AllowAnonymous]
        [HttpGet, Route("user/getPublicKey")]
        public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)
        {
            //var pemPublicKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey));

            return ResponseOutput.Ok(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey);
        }


        [HttpGet, Route("imageShare/ShareImage")]
        [AllowAnonymous]
        public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
        {
            var token = _tokenService.GetToken(new UserTokenInfo()
            {
                IdentityUserId = Guid.NewGuid(),
                UserName = "ImageShare",
                UserTypeEnum = UserTypeEnum.ShareImage,

            });
            return ResponseOutput.Ok("/showdicom?studyId=f7b67793-8155-0223-2f15-118f2642efb8&type=Share&token=" + token);
        }

        [HttpGet("user/GetObjectStoreToken")]
        public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
        {

            var domain = HttpContext.Request.Host.Host;


            var result = _oSSService.GetObjectStoreTempToken(domain);

  

            Log.Logger.Information($"使用域名:{domain}请求token.返回{result.ToJsonStr()}");

            return ResponseOutput.Ok(result);

        }


        private async Task<AWSTempToken> GetAWSTemToken(ObjectStoreServiceOptions serviceOption)
        {
            var awsOptions = serviceOption.AWS;

            //aws 临时凭证
            // 创建 STS 客户端
            var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);

            // 使用 AssumeRole 请求临时凭证
            var assumeRoleRequest = new AssumeRoleRequest
            {

                RoleArn = awsOptions.RoleArn, // 角色 ARN
                RoleSessionName = $"session-name-{NewId.NextGuid()}",
                DurationSeconds = awsOptions.DurationSeconds          // 临时凭证有效期
            };

            var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);

            var credentials = assumeRoleResponse.Credentials;

            var tempToken = new AWSTempToken()
            {
                AccessKeyId = credentials.AccessKeyId,
                SecretAccessKey = credentials.SecretAccessKey,
                SessionToken = credentials.SessionToken,
                Expiration = credentials.Expiration,
                Region = awsOptions.Region,
                BucketName = awsOptions.BucketName,
                EndPoint = awsOptions.EndPoint,
                ViewEndpoint = awsOptions.ViewEndpoint,

            };

            return tempToken;
        }


        #region 老项目依赖

        [HttpGet("user/GenerateSTS")]
        public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
        {

            var ossOptions = options.CurrentValue.AliyunOSS;

            var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
            {
                AccessKeyId = ossOptions.AccessKeyId,
                AccessKeySecret = ossOptions.AccessKeySecret,
                Endpoint = "sts.cn-hangzhou.aliyuncs.com"
            });

            var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
            // 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称，例如oss-role-session。
            assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
            // 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
            assumeRoleRequest.RoleArn = ossOptions.RoleArn;
            //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
            assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
            var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
            var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
            var credentials = response.Body.Credentials;

            var tempToken = new AliyunOSSTempToken()
            {
                AccessKeyId = credentials.AccessKeyId,
                AccessKeySecret = credentials.AccessKeySecret,

                //转为服务器时区，最后统一转为客户端时区
                Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
                SecurityToken = credentials.SecurityToken,


                Region = ossOptions.Region,
                BucketName = ossOptions.BucketName,
                EndPoint = ossOptions.EndPoint,
                ViewEndpoint = ossOptions.ViewEndpoint,
                PreviewEndpoint = ossOptions.PreviewEndpoint

            };

            // 返回STS令牌信息给前端
            var stsToken = new
            {
                AccessKeyId = credentials.AccessKeyId,
                AccessKeySecret = credentials.AccessKeySecret,
                SecurityToken = credentials.SecurityToken,
                Expiration = credentials.Expiration,

                Region = ossOptions.Region,
                BucketName = ossOptions.BucketName,
                ViewEndpoint = ossOptions.ViewEndpoint,

            };

            return ResponseOutput.Ok(stsToken);

        }

        #endregion


        [HttpGet("User/UserRedirect")]
        [AllowAnonymous]
        public async Task<IActionResult> UserRedirect([FromServices] IRepository<IdentityUser> _useRepository, string url, [FromServices] ILogger<ExtraController> _logger, [FromServices] ITokenService _tokenService)
        {

            var decodeUrl = System.Web.HttpUtility.UrlDecode(url);

            var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length, 36);

            var token = decodeUrl.Substring(decodeUrl.IndexOf("access_token=") + "access_token=".Length);

            var lang = decodeUrl.Substring(decodeUrl.IndexOf("lang=") + "lang=".Length, 2);

            var domainStrList = decodeUrl.Split("/").ToList().Take(3).ToList();

            var errorUrl = domainStrList[0] + "//" + domainStrList[2] + "/error";

            if (lang == "zh")
            {
                CultureInfo.CurrentCulture = new CultureInfo(StaticData.CultureInfo.zh_CN);
                CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.zh_CN);
            }
            else
            {
                CultureInfo.CurrentCulture = new CultureInfo(StaticData.CultureInfo.en_US);
                CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.en_US);
            }

            var isExpire = _tokenService.IsTokenExpired(token);

            if ( Guid.TryParse(userId,out _) == false || isExpire || !await _useRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd) )
            {
                decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(I18n.T("UserRedirect_InitializationLinkExpire"))} ";
            }

            return Redirect(decodeUrl);
        }




        #region 项目支持Oauth 对接修改

        /// <summary>
        /// 回调到前端，前端调用后端的接口 
        /// 参考链接：https://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
        /// 后端通过这个code ,带上客户端信息，和授权类型  可以向单点登录提供商，获取厂商token
        /// 
        /// 但是单点登录提供商提供的token 和我们系统的token 是有区别的，我们的token里面有我们业务系统的UserId，涉及到很多业务操作，所以在此出现了两种方案
        ///  1、前端使用厂商的Token。          后端通过code 获取厂商的Token 返回前端的同时返回我们系统的UserId，前段在http 请求头加上一个自定义参数，带上UserId  后端取用户Id的地方变动下，
        ///            但是除了UserId外，后端还有其他信息也是从Token取的，所以在请求头也需要带上，此外后端认证Token的方式也需要变化，改造成本稍大（如果是微服务，做这种处理还是可以的）。
        ///  2、前端还是使用我们后台自己的Token。后端通过code 获取厂商Token的同时，后端做一个隐藏登录，返回厂商的Token的同时，也返回我们系统的Token。
        ///  （像我们单体，这种方式最简单，我们用单点登录，无非就是不想记多个系统的密码，自动登录而已，其他不支持的项目改造成本也是最低的）
        /// </summary>
        /// <param name="type">回调的厂商类型 比如github, google, 我们用的logto  ,不同的厂商回调到前端的地址可以不同的，但是请求后端的接口可以是同一个 </param>
        /// <param name="code">在第三方平台登录成功后，回调前端的时候会返回一个code   </param>
        /// <returns></returns>
        [HttpGet("User/OAuthCallBack")]
        public async Task<IResponseOutput> OAuthCallBack(string type, string code)
        {
            #region 获取AccessTo

            //var headerDic = new Dictionary<string, string>();
            //headerDic.Add("code", code);
            //headerDic.Add("grant_type", "authorization_code");
            //headerDic.Add("redirect_uri", "http://localhost:6100");
            //headerDic.Add("scope", "all");

            #endregion




            return ResponseOutput.Ok();
        }




        #endregion

        #region 测试获取用户 ip
        [HttpGet, Route("ip")]
        [AllowAnonymous]
        public IResponseOutput Get([FromServices] IHttpContextAccessor _context)
        {

            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"RemoteIpAddress：{_context.HttpContext.Connection.RemoteIpAddress}");

            if (Request.Headers.ContainsKey("X-Real-IP"))
            {
                sb.AppendLine($"X-Real-IP：{Request.Headers["X-Real-IP"].ToString()}");
            }

            if (Request.Headers.ContainsKey("X-Forwarded-For"))
            {
                sb.AppendLine($"X-Forwarded-For：{Request.Headers["X-Forwarded-For"].ToString()}");
            }
            return ResponseOutput.Ok(sb.ToString());
        }


        [HttpGet, Route("ip2")]
        [AllowAnonymous]
        public IResponseOutput Get2([FromServices] IHttpContextAccessor _context)
        {

            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"RemoteIpAddress：{_context.HttpContext.Connection.RemoteIpAddress}");

            if (Request.Headers.ContainsKey("X-Real-IP"))
            {
                sb.AppendLine($"X-Real-IP：{Request.Headers["X-Real-IP"].ToString()}");
            }

            if (Request.Headers.ContainsKey("X-Forwarded-For"))
            {
                sb.AppendLine($"X-Forwarded-For：{Request.Headers["X-Forwarded-For"].ToString()}");
            }
            return ResponseOutput.Ok(sb.ToString());
        }
        #endregion



    }
}
