using System.Net;
using System.Text;
using System;
using System.Security.Cryptography;
using System.Collections.Generic;

namespace JiaZhiQuan.Common.KDNiao
{
    /// <summary>
    /// 快递鸟请求数据
    /// </summary>
    public class KDNiaoRequest
    {
        /// <summary>
        /// apikey
        /// </summary>
        private string ApiKey;
        public KDNiaoRequest(string EBusinessID, string ApiKey, string RequestData, KDNiaoRequestType RequestType)
        {
            this.ApiKey = ApiKey;
            this.EBusinessID = EBusinessID;
            this.RequestData = RequestData.Replace(" ", "");
            this.RequestType = RequestType;
            GenerateDataSign();
        }
        /// <summary>
        /// 请求参数
        /// </summary>
        public string RequestData { get; }
        /// <summary>
        /// 用户id
        /// </summary>
        public string EBusinessID { get; }
        /// <summary>
        /// 请求接口类型
        /// </summary>
        public KDNiaoRequestType RequestType { get; }
        /// <summary>
        /// 数据内容签名 (请求体(未编码)+ApiKey)进行MD5加密（32位小写），然后Base64编码，最后进行URL(utf-8)编码
        /// </summary>
        public string DataSign { get; private set; }
        public string DataType { get; } = "2";

        private void GenerateDataSign()
        {
            string jsonString = RequestData;
            string stringToSign = jsonString + ApiKey; // 拼接字符串和ApiKey
            string md5Hash = CalculateMD5Hash(stringToSign); // MD5加密
            string base64Encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(md5Hash)); // Base64编码
            DataSign = WebUtility.UrlEncode(base64Encoded); // URL编码
        }

        /// <summary>
        /// MD5 32位小写
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private static string CalculateMD5Hash(string input)
        {
            using (MD5 md5 = MD5.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2")); // 转换为32位小写的16进制字符串
                }
                return sb.ToString();
            }
        }
    }

    /// <summary>
    /// 快递鸟请求接口指令
    /// </summary>
    public enum KDNiaoRequestType
    {
        轨迹订阅_免费版 = 1008,
        轨迹订阅_增值版 = 8008,
        即时查询_免费版 = 1001,
        即时查询_增值版 = 8001,
        快递查询_增值版 = 8002
    }

    /// <summary>
    /// 快递鸟轨迹订阅接口返回参数
    /// </summary>
    public class KDNiaoTrackResponse
    {
        /// <summary>
        /// 快递公司编码
        /// </summary>
        public string ShipperCode { get; set; }
        /// <summary>
        /// 快递单号
        /// </summary>
        public string LogisticCode { get; set; }
        /// <summary>
        /// 更新时间
        /// </summary>
        public DateTime UpdateTime { get; set; } = DateTime.Now;
        /// <summary>
        /// 成功与否
        /// </summary>
        public bool Success { get; set; } = false;
    }

    /// <summary>
    /// 快递鸟callback轨迹参数
    /// </summary>
    public class KDNiaoTrackInfo
    {
        /// <summary>
        /// 推送时间，示例：2021-01-01 09:00:00
        /// </summary>
        public string PushTime { get; set; }
        /// <summary>
        /// 用户ID
        /// </summary>
        public string EBusinessID { get; set; }
        /// <summary>
        /// 推送的轨迹数据集合
        /// </summary>
        public List<KDNiaoTrackDataItem> Data { get; set; }
        /// <summary>
        /// 推送的快递单号个数
        /// </summary>
        public string Count { get; set; }
    }

    public class KDNiaoTrackDataItem
    {
        /// <summary>
        /// 物流状态编码
        /// </summary>
        /// 0-暂无轨迹信息
        /*
        1-已揽收
        2-在途中
         201-到达派件城市
         204-到达转运中心
         205-到达派件网点
         206-寄件网点发件
         202-派件中
         211-已放入快递柜或驿站
        3-已签收
         301-正常签收
         302-派件异常后最终签收
         304-代收签收
         311-快递柜或驿站签收
        4-问题件
         401-发货无信息
         402-超时未签收
         403-超时未更新
         404-拒收(退件)
         405-派件异常
         406-退货签收
         407-退货未签收
         412-快递柜或驿站超时未取
         413-单号已拦截
         414-破损
         415-客户取消发货
         416-无法联系
         417-配送延迟
         418-快件取出
         419-重新派送
         420-收货地址不详细
         421-收件人电话错误
         422-错分件
         423-超区件
        5-转寄
        6-清关
         601-待清关
         602-清关中
         603-已清关
         604-清关异常
        10-待揽件*/
        public string StateEx { get; set; }
        /// <summary>
        /// 快递单号
        /// </summary>
        public string LogisticCode { get; set; }
        /// <summary>
        /// 快递公司编码
        /// </summary>
        public string ShipperCode { get; set; }
        /// <summary>
        /// 轨迹信息
        /// </summary>
        public List<KDNiaoTrace> Traces { get; set; }
        /// <summary>
        /// 普通物流状态：
        /// </summary>
        /*
        0-暂无轨迹信息
        1-已揽收
        2-在途中
        3-签收
        4-问题件
        5-转寄
        6-清关*/
        public int State { get; set; }
        /// <summary>
        /// 当前城市
        /// </summary>
        public string Location { get; set; }
        /// <summary>
        /// 成功与否
        /// </summary>
        public bool Success { get; set; }
        /// <summary>
        /// 用户自定义回传字段
        /// </summary>
        public string Callback { get; set; }
        /// <summary>
        /// 失败原因
        /// </summary>
        public string Reason { get; set; }
        /// <summary>
        /// 用户id
        /// </summary>
        public string EBusinessID { get; set; }
        /// <summary>
        /// 快递员电话
        /// </summary>
        public string DeliveryManTel { get; set; }
    }

    public class KDNiaoTrace
    {
        /// <summary>
        /// 同上面 StateEx
        /// </summary>
        public string Action { get; set; }
        /// <summary>
        /// 轨迹描述
        /// </summary>
        public string AcceptStation { get; set; }
        /// <summary>
        /// 轨迹发生时间
        /// </summary>
        public string AcceptTime { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }
        /// <summary>
        /// 历史节点所在城市
        /// </summary>
        public string Location { get; set; }
    }
}
