using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using XYY.Data.Model.Standard.Tracking;

namespace XYY.Service.Standard.First.JobSubscribe
{
    public interface ISendFirstApi
    {
        Task<List<Logistics_TraceGroup>> Send(List<Logistics_TraceGroup> groups);

        List<TrackingTraceMeessageSendResult> SendMessage(List<XikeTraceMessage> messages);
    }

    public class XiKeApi : ISendFirstApi
    {
        public async Task<List<Logistics_TraceGroup>> Send(List<Logistics_TraceGroup> groups)
        {
            List<Logistics_TraceGroup> error = new List<Logistics_TraceGroup>();

            string Url = "http://tms-api.erp.chicv.com";
            string testToken = "eyJhbGciOiJIUzI1NiJ9.eyJjb21wYW55SWQiOjEwNDF9.R8EX-HOhR-lcE_lElZXXoErL_P7axf4193kQvqEqBcM";
            string token = "eyJhbGciOiJIUzI1NiJ9.eyJjb21wYW55SWQiOjEwNDF9.m5pPt91jKoohVxY9raNOAlB4cYcN0j_W9Dpex6gAkPw";
            System.Net.WebClient client = new System.Net.WebClient();
            client.Headers.Add("token", token);
            Uri uri = new Uri($"{Url}/openTracking/addTrackingEvent", false);
            for (int i = 0; i < Math.Ceiling(groups.Count() / 40.0); i++)
            {
                var g1 = groups.Skip(i * 40).Take(40).ToList();
                try
                {
                    var trackings = g1.Select(x => new XKTracking
                    {

                        requestOrder = x.CustomerOrderNo,
                        events = x.List.Select(y => new EventsItem
                        {
                            eventArea = y.Location ?? string.Empty,
                            eventDesc = y.StatusString,
                            eventTime = y.TriggerTime.ToString_yyyyMMddHHmmss(),
                            //eventTime = DateTime.Now.ToString_yyyyMMddHHmmss(),
                            eventStatus = y.Status.ToString()
                        }).ToList()
                    });
                    client.Proxy = new WebProxy("http://127.0.0.1:8888");
                    client.Headers.Add("Content-Type", "application/json");
                    string r = client.UploadString(uri, Newtonsoft.Json.JsonConvert.SerializeObject(trackings));
                    Result result = Newtonsoft.Json.JsonConvert.DeserializeObject<Result>(r);
                    if (result.isSuccess)
                    {
                        var d = result.data.Select(x => groups.Where(y => x == y.CustomerOrderNo).FirstOrDefault()).ToList();
                        error.AddRange(d);
                    }
                    else
                    {
                        error.AddRange(g1);
                    }
                }
                catch (System.Net.WebException ex)
                {
                    string text = string.Empty;
                    if (ex.Response != null && ex.Response.GetResponseStream() != null)
                    {
                        var rs = ex.Response.GetResponseStream();
                        var sr = new System.IO.StreamReader(rs);
                        text = sr.ReadToEnd();
                    }
                    Console.WriteLine("访问细刻api失败:" + ex.Message + ",服务器返回内容" + text);
                    error.AddRange(g1);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("访问细刻api失败:" + ex.Message + ",服务器返回内容" + ex.Message);
                    error.AddRange(g1);
                }

            }
            return error;

        }

        private int GetEventCode(TrackingEventType eventType)
        {
            switch (eventType)
            {
                case TrackingEventType.Arrive:
                    return 5;
                case TrackingEventType.Departure:
                    return 4;
                case TrackingEventType.Clearance:
                    return 6;
                case TrackingEventType.InStock:
                    return 2;
                case TrackingEventType.OutStock:
                    return 3;
                case TrackingEventType.Online:
                    return 8;
                default: return 0;
            }
        }


        public List<TrackingTraceMeessageSendResult> SendMessage(List<XikeTraceMessage> allMessagesList)
        {
            List<TrackingTraceMeessageSendResult> results = new List<TrackingTraceMeessageSendResult>();
            string Url = "http://tms-api.erp.chicv.com";
            string testToken = "eyJhbGciOiJIUzI1NiJ9.eyJjb21wYW55SWQiOjEwNDF9.R8EX-HOhR-lcE_lElZXXoErL_P7axf4193kQvqEqBcM";
            string token = "eyJhbGciOiJIUzI1NiJ9.eyJjb21wYW55SWQiOjEwNDF9.m5pPt91jKoohVxY9raNOAlB4cYcN0j_W9Dpex6gAkPw";
            System.Net.WebClient client = new System.Net.WebClient();
            Uri uri = new($"{Url}/openTracking/addTrackingEvent");
            client.Headers.Add("token", token);
            var allMessageByGroup = allMessagesList.GroupBy(x => x.CustomerNo);
            for (int i = 0; i < Math.Ceiling(allMessageByGroup.Count() / 40.0); i++)
            {
                var waitSendMesageList = allMessageByGroup.Skip(i * 40).Take(40).ToList();
                var trackings = waitSendMesageList.Select(x => new XKTracking
                {
                    requestOrder = x.Key,
                    events = x.Select(y => new EventsItem
                    {
                        eventArea = y.EventLoaction ?? string.Empty,
                        eventDesc = y.EventContent,
                        eventTime = y.EventTime.ToString_yyyyMMddHHmmss(),
                        eventStatus = GetEventCode(y.TrackingEventType).ToString()
                    }).Where(x => x.eventStatus != "0").ToList()
                });
                if (trackings.Count() > 0)
                {
                    client.Proxy = new WebProxy("http://127.0.0.1:8888");
                    client.Headers.Add("Content-Type", "application/json");
                    string json = null;
                    try
                    {
                        json = Newtonsoft.Json.JsonConvert.SerializeObject(trackings);
                    }
                    catch (Exception ex)
                    {
                        results.AddRange(waitSendMesageList.SelectMany(x => x.Select(y => new TrackingTraceMeessageSendResult
                        {
                            SendTime = DateTime.Now,
                            Key = y.Key,
                            ErrorMessage = "Json序列化失败:" + ex.Message,
                            IsSuccess = false
                        })));
                    }
                    if (json != null)
                    {
                        string r = null;
                        DateTime sendTime = DateTime.Now;
                        try
                        {
                            r = client.UploadString(uri, json);
                        }
                        catch (System.Net.WebException ex)
                        {
                            string text = string.Empty;
                            if (ex.Response != null && ex.Response.GetResponseStream() != null)
                            {
                                var rs = ex.Response.GetResponseStream();
                                var sr = new System.IO.StreamReader(rs);
                                text = sr.ReadToEnd();
                            }
                            Console.WriteLine("访问细刻api失败:" + ex.Message + ",服务器返回内容" + text);
                            results.AddRange(waitSendMesageList.SelectMany(x => x.Select(y => new TrackingTraceMeessageSendResult
                            {
                                SendTime = sendTime,
                                Key = y.Key,
                                ErrorMessage = "Http 结果解析失败:" + ex.Message + text,
                                IsSuccess = false
                            })));
                        }
                        catch (Exception ex)
                        {
                            results.AddRange(waitSendMesageList.SelectMany(x => x.Select(y => new TrackingTraceMeessageSendResult
                            {
                                SendTime = sendTime,
                                Key = y.Key,
                                ErrorMessage = "Http 请求失败:" + ex.Message,
                                IsSuccess = false
                            })));
                        }

                        Result httpResult = null;
                        try
                        {
                            httpResult =
                            Newtonsoft.Json.JsonConvert.DeserializeObject<Result>(r);
                        }
                        catch (Exception ex)
                        {
                            results.AddRange(waitSendMesageList.SelectMany(x => x.Select(y => new TrackingTraceMeessageSendResult
                            {
                                SendTime = sendTime,
                                Key = y.Key,
                                ErrorMessage = "Http 结果解析失败:" + ex.Message,
                                IsSuccess = false
                            })));
                        }

                        if (httpResult != null)
                        {

                            if (httpResult.isSuccess)
                            {
                                //错误订单
                                var errors = waitSendMesageList
                                    .Where(x => httpResult.data.Any(y => y == x.Key))
                                    .SelectMany(x => x.Select(z => new TrackingTraceMeessageSendResult
                                    {
                                        SendTime = sendTime,
                                        Key = z.Key,
                                        IsSuccess = false,
                                        ErrorMessage = httpResult.message
                                    }));
                                //正确订单
                                var success = waitSendMesageList
                                    .Where(x => !httpResult.data.Any(y => y == x.Key))
                                     .SelectMany(x => x.Select(z => new TrackingTraceMeessageSendResult
                                     {
                                         SendTime = sendTime,
                                         Key = z.Key,
                                         IsSuccess = true,
                                         ErrorMessage = httpResult.message
                                     }));
                                results.AddRange(errors);
                                results.AddRange(success);
                            }
                            else
                            {
                                results.AddRange(waitSendMesageList.SelectMany(x => x.Select(y => new TrackingTraceMeessageSendResult
                                {
                                    Key = y.Key,
                                    ErrorMessage = "Api 返回结果:" + httpResult.message,
                                    IsSuccess = false
                                })));
                            }
                        }
                    }
                }
            }
            results.Where(x => !x.IsSuccess && x.ErrorMessage == "SUCCESS").ToList().ForEach(x => x.IsSuccess = true);
            return results;
        }
    }

    public class Result
    {
        /// <summary>
        /// 
        /// </summary>
        public int code { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<string> data { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public object errors { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public bool isSuccess { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string message { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string timestamp { get; set; }
    }

    public class EventsItem
    {
        /// <summary>
        /// 
        /// </summary>
        public string eventArea { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string eventDesc { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string eventStatus { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string eventTime { get; set; }
    }

    public class XKTracking
    {
        /// <summary>
        /// 
        /// </summary>
        public int companyId { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<EventsItem> events { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string expressNo { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string requestOrder { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string trackingCode { get; set; }
    }

}
