using System;
using System.Net.Http;
using EasyCaching.Core;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Application.Interfaces;
using System.Threading.Tasks;
using IRaCIS.Application.Services;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure;
using System.Linq;
using Microsoft.Extensions.Logging;
using MassTransit;
using Microsoft.AspNetCore.Hosting;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.Core.Auth.Sts;
using Aliyun.Acs.Core;
using IRaCIS.Core.Application.Helper;
using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Contracts;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
using DocumentFormat.OpenXml.Spreadsheet;
using AutoMapper.QueryableExtensions;

namespace IRaCIS.Api.Controllers
{
    /// <summary>
    /// 医生基本信息 、工作信息  专业信息、审核状态
    /// </summary>
    [ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
    public class ExtraController : 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>
        [HttpGet, Route("doctor/getDetail/{doctorId:guid}")]

        public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
            [FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,

            [FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService, Guid doctorId)
        {
            var education = await _educationService.GetEducation(doctorId);

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

            var doctorDetail = new DoctorDetailDTO
            {
                AuditView = await _doctorService.GetAuditState(doctorId),
                BasicInfoView = await _doctorService.GetBasicInfo(doctorId),
                EmploymentView = await _doctorService.GetEmploymentInfo(doctorId),
                AttachmentList = await attachmentService.GetAttachments(doctorId),

                EducationList = education.EducationList,
                PostgraduateList = education.PostgraduateList,

                TrialExperienceView = await _trialExperienceService.GetTrialExperience(doctorId),
                ResearchPublicationView = await _researchPublicationService.GetResearchPublication(doctorId),

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

            return ResponseOutput.Ok(doctorDetail);
        }







        /// <summary>  系统用户登录接口[New] </summary>
        [HttpPost, Route("user/login")]
        [AllowAnonymous]
        public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
            [FromServices] IEasyCachingProvider provider,
            [FromServices] IUserService _userService,
             [FromServices] ITokenService _tokenService,
             [FromServices] IReadingImageTaskService readingImageTaskService,
             IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
              IMailVerificationService _mailVerificationService)
        {

            //MFA 邮箱验证  前端传递用户Id  和MFACode
            if (loginUser.UserId != null  && _verifyConfig.CurrentValue.OpenLoginMFA)
            {
                Guid userId = (Guid)loginUser.UserId;

                //验证MFA 编码是否有问题 ,前端要拆开,自己调用验证的逻辑
                //await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode);

                //var loginUser = await _userRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo<UserBasicInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();

                var basicInfo = await _userService.GetUserBasicInfo(userId, loginUser.Password);

                var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo };

                loginReturn.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(loginReturn.BasicInfo));


                // 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
                var option = new CookieOptions
                {
                    Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
                    HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
                    SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
                    Secure = false // 确保 cookie 只能通过 HTTPS 访问
                };

                HttpContext.Response.Cookies.Append("access_token", loginReturn.JWTStr, option);

                // 验证阅片休息时间
                await readingImageTaskService.ResetReadingRestTime(userId);

                await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));

                await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));

                return ResponseOutput.Ok(loginReturn);

            }
            else
            {
                var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);

                if (returnModel.IsSuccess)
                {
                    #region GRPC 调用鉴权中心,因为服务器IIS问题 http/2   故而没法使用

                    ////重试策略
                    //var defaultMethodConfig = new MethodConfig
                    //{
                    //    Names = { MethodName.Default },
                    //    RetryPolicy = new RetryPolicy
                    //    {
                    //        MaxAttempts = 3,
                    //        InitialBackoff = TimeSpan.FromSeconds(1),
                    //        MaxBackoff = TimeSpan.FromSeconds(5),
                    //        BackoffMultiplier = 1.5,
                    //        RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
                    //    }
                    //};

                    //#region  unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate

                    //var httpHandler = new HttpClientHandler();
                    //// Return `true` to allow certificates that are untrusted/invalid
                    //httpHandler.ServerCertificateCustomValidationCallback =
                    //    HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;


                    //////这一句是让grpc支持本地 http  如果本地访问部署在服务器上,那么是访问不成功的 
                    //AppContext.SetSwitch(
                    //    "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

                    //#endregion



                    //var grpcAdress = configuration.GetValue<string>("GrpcAddress");
                    ////var grpcAdress = "http://localhost:7200";

                    //var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
                    //{
                    //    HttpHandler = httpHandler,
                    //    ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }

                    //});
                    ////var channel = GrpcChannel.ForAddress(grpcAdress);
                    //var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);

                    //var userInfo = returnModel.Data.BasicInfo;

                    //var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
                    //{
                    //    Id = userInfo.Id.ToString(),
                    //    ReviewerCode = userInfo.ReviewerCode,
                    //    IsAdmin = userInfo.IsAdmin,
                    //    RealName = userInfo.RealName,
                    //    UserTypeEnumInt = (int)userInfo.UserTypeEnum,
                    //    UserTypeShortName = userInfo.UserTypeShortName,
                    //    UserName = userInfo.UserName
                    //});

                    //returnModel.Data.JWTStr = tokenResponse.Token;

                    #endregion

                    var userId = returnModel.Data.BasicInfo.Id;

                    if (_verifyConfig.CurrentValue.OpenLoginMFA)
                    {
                        //发版屏蔽

                        //returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));

                        //MFA 发送邮件

                        returnModel.Data.IsMFA = true;

                        var email = returnModel.Data.BasicInfo.EMail;

                        #region 隐藏Email
                        // 找到 "@" 符号的位置
                        int atIndex = email.IndexOf('@');
                       
                        // 替换 "@" 符号前的中间两位为星号
                        string visiblePart = email.Substring(0, atIndex);

                        int startIndex = (visiblePart.Length - 2) / 2;

                        // 替换中间两位字符为星号
                        string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
                       
                        string afterAt = email.Substring(atIndex + 1);
                       
                        // 组合隐藏和可见部分
                        string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
                        #endregion

                        returnModel.Data.BasicInfo.EMail = hiddenEmail;

                        await _userService.SendMFAEmail(userId);

                    }
                    else
                    {
                        returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));

                        // 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
                        var option = new CookieOptions
                        {
                            Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
                            HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
                            SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
                            Secure = false // 确保 cookie 只能通过 HTTPS 访问
                        };

                        HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);



                        // 验证阅片休息时间
                        await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);

                        await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));

                        await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
                    }

                }
                return returnModel;

            }




        }





        [HttpGet, Route("imageShare/ShareImage")]
        [AllowAnonymous]
        public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
        {
            var token = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo()
            {
                Id = Guid.Empty,
                IsReviewer = false,
                IsAdmin = false,
                RealName = "Share001",
                UserName = "Share001",
                Sex = 0,
                //UserType = "ShareType",
                UserTypeEnum = UserTypeEnum.ShareImage,
                Code = "ShareCode001",
            }));
            return ResponseOutput.Ok("/showdicom?studyId=f7b67793-8155-0223-2f15-118f2642efb8&type=Share&token=" + token);
        }

        [HttpGet("user/GetObjectStoreToken")]
        public IResponseOutput GetObjectStoreToken([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
        {
            var serviceOption = options.CurrentValue;

            if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS)
            {

                var ossOptions = serviceOption.AliyunOSS;

                return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS });

                #region 临时token 屏蔽
                //IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
                //DefaultAcsClient client = new DefaultAcsClient(profile);


                //// 创建一个STS请求
                //AssumeRoleRequest request = new AssumeRoleRequest
                //{
                //    RoleArn = ossOptions.RoleArn, // 角色ARN,需要替换为你的角色ARN
                //    RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
                //    DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
                //};


                //AssumeRoleResponse response = client.GetAcsResponse(request);

                //// 返回STS令牌信息给前端
                //var stsToken = new ObjectStoreDTO()
                //{
                //    ObjectStoreUse = serviceOption.ObjectStoreUse,
                //    AliyunOSS = new AliyunOSSTempToken()
                //    {
                //        AccessKeyId = response.Credentials.AccessKeyId,
                //        AccessKeySecret = response.Credentials.AccessKeySecret,
                //        SecurityToken = response.Credentials.SecurityToken,
                //        Expiration = response.Credentials.Expiration,

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

                //    },
                //    MinIO = serviceOption.MinIO
                //};
                //return ResponseOutput.Ok(stsToken);

                #endregion

            }
            else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
            {
                return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
            }
            else
            {
                return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
            }

        }

        [HttpGet("user/GenerateSTS")]
        public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
        {
            var ossOptions = options.CurrentValue;


            IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);


            // 创建一个STS请求
            AssumeRoleRequest request = new AssumeRoleRequest
            {
                RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
                RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
                DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
            };


            AssumeRoleResponse response = client.GetAcsResponse(request);

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

                Region = ossOptions.region,
                BucketName = ossOptions.bucketName,
                ViewEndpoint = ossOptions.viewEndpoint,

            };

            return ResponseOutput.Ok(stsToken);

        }



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

            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 (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
            {
                decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang == "zh" ? "您的初始化链接已过期" : "Error!The initialization link has expired.    Return")} ";
            }

            return Redirect(decodeUrl);
        }





        [HttpGet, Route("ip")]
        [AllowAnonymous]
        public IResponseOutput Get([FromServices] IHttpContextAccessor _context/*, [FromServices] IUserService _userService*/)
        {

            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, [FromServices] IRepository _userService)
        {

            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());
        }

    }
}