using SimpleCore;
using SimpleCore.Library;
using StandardScene.Utils;
using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using StandardScene.Model;

namespace StandardScene.Chained
{
    /// <summary>
    /// 统一管理 TransportDelivery 相关的任务回调方法，并通过回调注册表提供可恢复性。
    /// </summary>
    public static class TransportDeliveryCallbacks
    {
        public const string KeyOnStarted    = "Transport.OnMissionStarted";
        public const string KeyOnFetched    = "Transport.OnFetched";
        public const string KeyOnPut        = "Transport.OnPut";
        public const string KeyOnFinished   = "Transport.OnMissionFinished";
        public const string KeyOnFailed     = "Transport.OnMissionFailed";
        public const string KeyOnTerminated = "Transport.OnMissionTerminated";

        private static bool _initialized;
        private static readonly HttpClient _httpClient = new HttpClient();
        private static string _callbackUrl = "http://127.0.0.1:20101/api/v1/MDCS/State";

        static TransportDeliveryCallbacks()
        {
            if (_initialized) return;
            _initialized = true;

            DeliveryCallbackRegistry.RegisterOnStart   (KeyOnStarted,    OnMissionStarted);
            DeliveryCallbackRegistry.RegisterDoneFetch (KeyOnFetched,    OnFetched);
            DeliveryCallbackRegistry.RegisterDonePut   (KeyOnPut,        OnPut);
            DeliveryCallbackRegistry.RegisterDoneMission(KeyOnFinished,  OnMissionFinished);
            DeliveryCallbackRegistry.RegisterFailed    (KeyOnFailed,     OnMissionFailed);
            DeliveryCallbackRegistry.RegisterOnTerminated(KeyOnTerminated, OnMissionTerminated);
        }

        /// <summary>
        /// 显式调用以确保静态构造函数已执行（注册所有默认回调）。
        /// </summary>
        public static void EnsureInitialized()
        {
            // 访问本类，确保静态构造已执行
            if (!_initialized)
            {
                // 触发 static ctor（CLR 保证线程安全）
                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(TransportDeliveryCallbacks).TypeHandle);
            }
        }

        /// <summary>
        /// 配置任务状态回调的完整 URL（例如 http://ip:port/api/v1/MDCS/State）。
        /// 建议在 TransportMission 启动或构造时调用一次。
        /// </summary>
        public static void ConfigureCallbackUrl(string url)
        {
            if (!string.IsNullOrWhiteSpace(url))
            {
                _callbackUrl = url;
            }
        }

        private static void DispatchMissionState(TransportDelivery d, MissionState.MissionStateEnum state)
        {
            var ms = new MissionState
            {
                MissionId   = d.TaskId,
                CarCode     = d.UsingCar?.id.ToString() ?? "0",
                TriggerTime = DateTime.Now,
                State       = state
            };
            MissionStatePost(ms);
        }

        private static async void MissionStatePost(MissionState ms)
        {
            var retryCount = 10;
            var retryDelay = TimeSpan.FromSeconds(1);
            var content = new StringContent(ms.ToJson());
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            for (int i = 0; i < retryCount; i++)
            {
                try
                {
                    var resp = await _httpClient.PostAsync(_callbackUrl, content);
                    Diagnosis.Post($"{ms.State}回调结果 => {resp.Content.ReadAsStringAsync().Result}");
                    var body = resp.Content.ReadAsStringAsync().Result.JsonTo<BaseRespose>();
                    var result = body.Code == 200 ? "成功" : "失败";
                    Diagnosis.Post($"车辆编号：{ms.CarCode} 任务id：{ms.MissionId} 状态回调执行{result}");
                    break;
                }
                catch (Exception ex)
                {
                    Diagnosis.Log($"{ms.State}状态回调失败 => ex:{ex}");
                    if (i == retryCount - 1)
                    {
                        Diagnosis.Log($"StringContent:{content}", "apiError");
                    }
                    await Task.Delay(retryDelay);
                }
            }
        }

        public static async void OnMissionStarted(ChainedDeliveryMission.Delivery delivery)
        {
            var d = (TransportDelivery)delivery;
            Diagnosis.Log($"task(#{d.TaskId}) started");

            if (!string.IsNullOrWhiteSpace(d.TaskIdsString))
            {
                Commons.AddOrUpdateTag(d.UsingCar.tags, "taskIdsString", d.TaskIdsString);
                Diagnosis.Log(
                    $"holdCarTagAddOrUpdate--TaskId:{d.TaskId},task:[{d.ToJson()}].taskIdsString:{d.TaskIdsString}",
                    "holdCarTag",
                    true);
            }

            Commons.DeleteTag(d.UsingCar.tags, "holdCar");
            if (!string.IsNullOrEmpty(d.HoldCarSite))
            {
                Commons.AddOrUpdateTag(d.UsingCar.tags, "holdCar", d.HoldCarSite);
                Diagnosis.Log(
                    $"holdCarTagAddOrUpdate--TaskId:{d.TaskId},task:[{d.ToJson()}].holdCar:{d.HoldCarSite}",
                    "holdCarTag",
                    true);
            }

            DispatchMissionState(d, MissionState.MissionStateEnum.Started);
        }

        public static async void OnFetched(ChainedDeliveryMission.Delivery delivery)
        {
            var d = (TransportDelivery)delivery;
            if (d.Src == d.Dst) return;

            Diagnosis.Log($"task(#{d.TaskId}) fetched");
            DispatchMissionState(d, MissionState.MissionStateEnum.Fetched);
        }

        public static async void OnPut(ChainedDeliveryMission.Delivery delivery)
        {
            var d = (TransportDelivery)delivery;
            if (d.Src == d.Dst) return;

            Diagnosis.Log($"task(#{d.TaskId}) put");
            DispatchMissionState(d, MissionState.MissionStateEnum.Put);
        }

        public static async void OnMissionFailed(ChainedDeliveryMission.Delivery delivery)
        {
            var d = (TransportDelivery)delivery;
            Diagnosis.Log($"task(#{d.TaskId}) failed");
            DispatchMissionState(d, MissionState.MissionStateEnum.Failed);
        }

        public static async void OnMissionFinished(ChainedDeliveryMission.Delivery delivery)
        {
            var d = (TransportDelivery)delivery;
            Diagnosis.Log($"task(#{d.TaskId}) finished");

            if (!string.IsNullOrWhiteSpace(d.MGTaskCode!) && d.MGTaskCode.Contains("-"))
            {
                var phase = d.MGTaskCode.Split('-')[1];
                var last = int.Parse(phase) - 1;
                if (last > 0 && string.IsNullOrWhiteSpace(d.TaskIdsString))
                {
                    var holdCar = SimpleLib.GetAllCars()
                        .FirstOrDefault(e => e.tags.TryGetValue("taskIdsString", out var v) && v.Contains(d.TaskId));
                    if (holdCar != null)
                    {
                        Commons.DeleteTag(holdCar.tags, "taskIdsString");
                        Diagnosis.Log(
                            $"holdCarTagDelete-2：OnMissionFinished--TaskId:{d.TaskId},task:[{d.ToJson()}].taskIdsString:{d.TaskIdsString}",
                            "holdCarTag",
                            true);
                    }
                }
            }

            DispatchMissionState(d, MissionState.MissionStateEnum.Finished);
        }

        public static async Task<int> OnMissionTerminated(ChainedDeliveryMission.Delivery delivery, string ISRelease)
        {
            try
            {
                using var hc = new HttpClient();
                var task = await hc.GetAsync($"http://{delivery.UsingCar.address}:8008/car/startOrPause?ISRelease={ISRelease}");
                var resp = task.Content.ReadAsStringAsync().Result.JsonTo<BaseRespose>();
                var result = resp.Code == 200 ? "成功" : "失败";
                return 1;
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"暂停恢复失败 => ex:{ExceptionFormatter.FormatEx(ex)}");
                return 0;
            }
        }
    }
}

