using DataSharing.Application.Identity;
using DataSharing.CityStateDataExchange;
using DataSharing.FwDataExchange;
using DataSharing.RawData;
using DataSharing.Share.Dtos;
using DataSharing.Share.Dtos.CityStateDataExchange;
using DataSharing.Share.Dtos.HotlineSetting;
using DotNetCore.CAP;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.OrderTranspond;
using Hotline.Share.Enums.Order;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using XF.Domain.Filters;
using XF.Domain.Repository;

namespace DataSharing.Host.Controllers
{
    /// <summary>
    /// 市州数据交换
    /// </summary>
    public class CityDataExchangeController : BaseController
    {
        private readonly IMapper _mapper;
        private readonly IMediator _mediator;
        private readonly ICapPublisher _capPublisher;
        private readonly IChannelConfigurationManager _channelConfigurationManager;
        private readonly IRepository<DsReceiveDataExchangeData> _dsReceiveDataExchangeDataRepository;
        private readonly FwClient _fwClient;
        private readonly IRepository<DsUserTokenInfo> _dsUserTokenInfoRepository;
        private readonly ISharingSessionContext _sessionContext;
        private readonly IRepository<DsReceiveHandleData> _dsReceiveHandleDataRepository;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mapper"></param>
        /// <param name="mediator"></param>
        /// <param name="capPublisher"></param>
        /// <param name="channelConfigurationManager"></param>
        /// <param name="dsReceiveDataExchangeDataRepository"></param>
        /// <param name="fwClient"></param>
        /// <param name="dsUserTokenInfoRepository"></param>
        /// <param name="sessionContext"></param>
        /// <param name="dsReceiveHandleDataRepository"></param>
        public CityDataExchangeController(IMapper mapper, IMediator mediator,
            ICapPublisher capPublisher,
            IChannelConfigurationManager channelConfigurationManager,
            IRepository<DsReceiveDataExchangeData> dsReceiveDataExchangeDataRepository,
            FwClient fwClient,
            IRepository<DsUserTokenInfo> dsUserTokenInfoRepository,
            ISharingSessionContext sessionContext,
            IRepository<DsReceiveHandleData> dsReceiveHandleDataRepository)
        {
            _mapper = mapper;
            _mediator = mediator;
            _capPublisher = capPublisher;
            _channelConfigurationManager = channelConfigurationManager;
            _dsReceiveDataExchangeDataRepository = dsReceiveDataExchangeDataRepository;
            _fwClient = fwClient;
            _dsUserTokenInfoRepository = dsUserTokenInfoRepository;
            _sessionContext = sessionContext;
            _dsReceiveHandleDataRepository = dsReceiveHandleDataRepository;
        }

        /// <summary>
        /// 市州互转
        /// </summary>
        /// <param name="dto">数据互换</param>
        /// <returns></returns>
        [HttpPost("city_exchange_add_order")]
        public async Task<OpenResponse> CityExchangeAddOrder([FromBody] OrderDto dto)
        {
            // 验证
            if (dto is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "数据解析失败"));

            //写入原始数据表
            var data = new DsReceiveDataExchangeData()
            {
                ExternalId = dto.No,
                ServiceInterface = "city_exchange_add_order",
                PlatformsName = _sessionContext.PlatformSourceName,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto)
            };
            await _dsReceiveDataExchangeDataRepository.AddAsync(data, HttpContext.RequestAborted);

            var orderData = new AddOrderDto();// _mapper.Map<AddOrderDto>(dto);
            orderData.CallAddress = dto.CallAddress;
            orderData.FromPhone = dto.FromPhone;
            orderData.TransferPhone = dto.TransferPhone;
            orderData.FromName = dto.FromName;
            orderData.FromGender = dto.FromGender;
            orderData.IdentityType = dto.IdentityType;
            orderData.LicenceTypeCode = dto.LicenceTypeCode;
            orderData.LicenceType = dto.LicenceType;
            orderData.LicenceNo = dto.LicenceNo;
            orderData.AgeRangeCode = dto.AgeRangeCode;
            orderData.AgeRange = dto.AgeRange;
            orderData.Contact = dto.Contact;
            orderData.AcceptSms = dto.AcceptSms;
            orderData.SmsSended = dto.SmsSended;
            orderData.IsSecret = dto.IsSecret;
            orderData.Company = dto.Company;
            orderData.AcceptType = dto.AcceptType;
            orderData.AcceptTypeCode = dto.AcceptTypeCode;
            orderData.Title = dto.Title;
            orderData.HotspotId = dto.HotspotId;
            orderData.HotspotName = dto.HotspotName;
            orderData.HotspotSpliceName = dto.HotspotSpliceName;
            orderData.HotspotExternal = dto.HotspotExternal;
            orderData.EventCategoryId = dto.EventCategoryId;
            orderData.EventCategoryName = dto.EventCategoryName;
            orderData.EventCategorySpliceName = dto.EventCategorySpliceName;
            orderData.EventCategoryExternal = dto.EventCategoryExternal;
            orderData.IncidentTime = dto.IncidentTime;
            orderData.IncidentPurpose = dto.IncidentPurpose;
            orderData.DuplicateIds = dto.DuplicateIds;
            orderData.PushTypeCode = dto.PushTypeCode;
            orderData.PushType = dto.PushType;
            orderData.OrderPushTypes = dto.OrderPushTypes;
            orderData.Additions = dto.Additions;
            orderData.Content = dto.Content;
            orderData.OrderExtension = dto.OrderExtension;
            orderData.Files = dto.Files;
            orderData.IsProvince = dto.IsProvince;
            orderData.Longitude = dto.Longitude;
            orderData.Latitude = dto.Latitude;
            orderData.AreaCode = dto.AreaCode;
            orderData.Province = dto.Province;
            orderData.City = dto.City;
            orderData.County = dto.County;
            orderData.Town = dto.Town;
            orderData.Street = dto.Street;
            orderData.Transpond = false;
            orderData.SourceChannel = "市州互转";
            orderData.SourceChannelCode = "SZHZ";
            orderData.ExternalId = dto.No;
            orderData.Source = dto.Source;

            var result = await _fwClient.RequestNoTokenAsync<HotlineClientResponse>("api/v1/Order/add-anonymous", "Post", System.Text.Json.JsonSerializer.Serialize(orderData));

            if (result != null && result.code == 0)
            {
                var cityName = "";
                switch (dto.Source)
                {
                    case ESource.CityDataExchangeLz:
                        cityName = "泸州12345";
                        break;
                    case ESource.CityDataExchangeYB:
                        cityName = "宜宾12345";
                        break;
                    case ESource.CityDataExchangeZG:
                        cityName = "自贡12345";
                        break;
                    default:
                        break;
                }
                TranspondCityRawDataDto cityRawDataDto = new()
                {
                    OrderCode = dto.No,
                    TransferOutTime = DateTime.Now,
                    SendTimes = 1,
                    IsSuccess = true,
                    Result = System.Text.Json.JsonSerializer.Serialize(dto),
                    CityName = cityName,
                    Direction = ETranspondDirection.In,
                    NewCode = result.result.no
                };
                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SharingOrderReceiveTranspondCity, cityRawDataDto, cancellationToken: HttpContext.RequestAborted);

                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Success(result.result.no, result.result.password, "您已成功提交数据！"));
            }
            else
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "接口调用失败！"));
        }

        /// <summary>
        /// 办理结果
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("city_exchange_add_opinion")]
        public async Task<OpenResponse> CityExchangeAddOpinion([FromBody] CityExchangeAddOpinionDto dto)
        {
            // 验证
            if (dto is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "数据解析失败"));

            //写入原始数据表
            var data = new DsReceiveDataExchangeData()
            {
                ExternalId = dto.OrderId,
                ServiceInterface = "city_exchange_add_opinion",
                PlatformsName = dto.TranspondCityName,// _sessionContext.PlatformSourceName,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto)
            };
            await _dsReceiveDataExchangeDataRepository.AddAsync(data, HttpContext.RequestAborted);

            //写入对外展示表数据
            DsReceiveHandleData dsReceive = new()
            {
                OrderNo = dto.OrderId,
                Source = "市州互转",
                PlatformsName = dto.TranspondCityName,// 、、_sessionContext.PlatformSourceName,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto),
                OperationType = "市州互转办理结果",
                Opinion = dto.ActualOpinion
            };
            await _dsReceiveHandleDataRepository.AddAsync(dsReceive, HttpContext.RequestAborted);

            TranspondCityOrderResultDto transpondCityOrderResultDto = new()
            {
                No = dto.OrderId,
                Opinion = dto.ActualOpinion
            };
            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SharingOrderReceiveHandleOpinionTranspondCity, transpondCityOrderResultDto, cancellationToken: HttpContext.RequestAborted);

            return OpenResponse.Ok(CityStateDataExchangeDeReponse.Success("", "", "您已成功提交数据！"));
        }

        /// <summary>
        /// 市州互转---工单推送业务
        /// </summary>
        /// <param name="dto">宜宾泸州数据互换</param>
        /// <returns></returns>
        [HttpPost("city_hand_data")]
        [AllowAnonymous]
        public async Task<OpenResponse> CityHandData([FromForm] CityStateDataReceiveDto dto)
        {
            // 验证
            if (dto is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "数据解析失败"));

            dto.ServerName = HttpUtility.UrlDecode(dto.ServerName);
            dto.PurTypeName = HttpUtility.UrlDecode(dto.PurTypeName);
            dto.ConTypeName = HttpUtility.UrlDecode(dto.ConTypeName);
            dto.Title = HttpUtility.UrlDecode(dto.Title);
            dto.LinkName = HttpUtility.UrlDecode(dto.LinkName);
            dto.Address = HttpUtility.UrlDecode(dto.Address);
            dto.Content = HttpUtility.UrlDecode(dto.Content);
            dto.Source = HttpUtility.UrlDecode(dto.Source);

            //验证数据
            string strResult = dto.Validate();
            if (!string.IsNullOrEmpty(strResult))
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: strResult));

            var userInfo = await _dsUserTokenInfoRepository.GetAsync(p => p.PlatformSourceName == dto.Source, HttpContext.RequestAborted);
            if (userInfo is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed("-900", "密钥错误"));

            //验证MD5
            strResult = Verification(dto.Code, dto.Source + userInfo.AccountSecret);
            if (!string.IsNullOrEmpty(strResult))
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed("-900", strResult));

            //写入原始数据表
            var data = new DsReceiveDataExchangeData()
            {
                ExternalId = dto.FSHCode,
                ServiceInterface = "city_hand_data",
                PlatformsName = userInfo.PlatformSourceName,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto)
            };
            data.Id = await _dsReceiveDataExchangeDataRepository.AddAsync(data, HttpContext.RequestAborted);

            Hotline.Share.Dtos.Order.AddOrderDto orderDto = new()
            {
                Title = dto.Title,
                ExternalId = dto.FSHCode,
                AcceptType = dto.PurTypeName,
                HotspotSpliceName = dto.ConTypeName,
                FromName = dto.LinkName,
                Contact = dto.Mobile,
                FullAddress = dto.Address,
                Content = dto.Content,
                Source = (ESource)Enum.Parse(typeof(ESource), userInfo.PlatformSource),
                FromGender = dto.Gender switch
                {
                    "1" => EGender.Male,
                    "2" => EGender.Female,
                    _ => EGender.Unknown,
                },
                SourceChannel = "市州互转",
                SourceChannelCode = "SZHZ",
                IdentityType = EIdentityType.Citizen,
                Transpond = false,
                IsEnforcementOrder = false
            };

            var result = await _fwClient.RequestNoTokenAsync<HotlineClientResponse>("api/v1/Order/add-anonymous", "Post", System.Text.Json.JsonSerializer.Serialize(orderDto));

            if (result != null && result.code == 0)
            {
                TranspondCityRawDataDto cityRawDataDto = new()
                {
                    OrderCode = dto.FSHCode,
                    TransferOutTime = DateTime.Now,
                    SendTimes = 1,
                    IsSuccess = true,
                    Result = System.Text.Json.JsonSerializer.Serialize(dto),
                    CityName = dto.Source,
                    Direction = ETranspondDirection.In,
                    NewCode = result.result.no
                };
                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SharingOrderReceiveTranspondCity, cityRawDataDto, cancellationToken: HttpContext.RequestAborted);

                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Success(result.result.no, result.result.password, "您已成功提交数据！"));
            }
            else
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "接口调用失败！"));
        }

        /// <summary>
        /// 办理结果
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("city_undertak_advice_data")]
        [AllowAnonymous]
        public async Task<OpenResponse> CityDataUndertakAdvice([FromForm] CityDataUndertakAdviceDto dto)
        {
            // 验证
            if (dto is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: "数据解析失败"));

            dto.UndertakAdvice = HttpUtility.UrlDecode(dto.UndertakAdvice);
            dto.Source = HttpUtility.UrlDecode(dto.Source);

            //验证数据
            string strResult = dto.Validate();
            if (!string.IsNullOrEmpty(strResult))
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed(description: strResult));

            var userInfo = await _dsUserTokenInfoRepository.GetAsync(p => p.PlatformSourceName == dto.Source, HttpContext.RequestAborted);
            if (userInfo is null)
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed("-900", "密钥错误"));

            //验证MD5
            strResult = Verification(dto.Code, dto.Source + userInfo.AccountSecret);
            if (!string.IsNullOrEmpty(strResult))
                return OpenResponse.Ok(CityStateDataExchangeDeReponse.Failed("-900", strResult));

            //写入原始数据表
            var data = new DsReceiveDataExchangeData()
            {
                ExternalId = dto.SCDRCode,
                ServiceInterface = "city_undertak_advice_data",
                PlatformsName = userInfo.PlatformSourceName,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto)
            };
            await _dsReceiveDataExchangeDataRepository.AddAsync(data, HttpContext.RequestAborted);

            //写入对外展示表数据
            DsReceiveHandleData dsReceive = new()
            {
                OrderNo = dto.SCDRCode,
                Source = "市州互转",
                PlatformsName = dto.Source,
                ReceiveData = System.Text.Json.JsonSerializer.Serialize(dto),
                OperationType = "市州互转办理结果",
                Opinion = dto.UndertakAdvice
            };
            await _dsReceiveHandleDataRepository.AddAsync(dsReceive, HttpContext.RequestAborted);

            TranspondCityOrderResultDto transpondCityOrderResultDto = new()
            {
                No = dto.SCDRCode,
                Opinion = dto.UndertakAdvice
            };
            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.SharingOrderReceiveHandleOpinionTranspondCity, transpondCityOrderResultDto, cancellationToken: HttpContext.RequestAborted);

            return OpenResponse.Ok(CityStateDataExchangeDeReponse.Success("", "", "您已成功提交数据！"));
        }

        #region 密钥验证

        /// <summary>
        /// 密钥验证
        /// </summary>
        /// <param name="Code"></param>
        /// <param name="Source"></param>
        /// <returns></returns>
        private static string Verification(string Code, string Source)
        {
            string strJJYLCode = GetMD5(Source);
            if (strJJYLCode.ToLower().Trim() != Code.ToLower().Trim())
                return "密钥错误";
            return "";
        }

        #endregion

        #region MD5 32位加密

        /// <summary>
        /// MD5 32位加密
        /// </summary>
        /// <param name="myString"></param>
        /// <returns></returns>
        private static string GetMD5(string myString)
        {
            string cl = myString;
            string pwd = "";
            try
            {
                MD5 md5 = MD5.Create();//实例化一个md5对像
                                       // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
                byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
                // 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得
                for (int i = 0; i < s.Length; i++)
                {
                    // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符 
                    pwd = pwd + s[i].ToString("X2");
                }
            }
            catch (Exception)
            {
            }
            return pwd;
        }

        #endregion
    }
}
