using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleCore;
using Newtonsoft.Json;
using SimpleLite.CADTools;
using SimpleLite.Props;
using SimpleLite.UI;
using SimpleCore.Library;
using System.Threading.Tasks;
using System.Diagnostics;
using SimpleCore.Traffic;
using SimpleCore.PropType;
using LessokajiWeaverUtilities.Utilities;

namespace StandardScene.Scheduler
{
    [MissionType(Name = "区域流量监控", editor = typeof(RegionalTrafficControlMission))]
    [I18N.DocumentTranslation(Name = "Regional Traffic Control Mission", locale = "en")]
    public class RegionalTrafficControlMission : Mission
    {
        public static Mission Create()
        {
            return new RegionalTrafficControlMission();
        }

        /// <summary>
        /// 区域流量监控状态
        /// </summary>
        public class RegionalTrafficControlMissionStatus : MissionStatus
        {
            /// <summary>
            /// 区域车辆统计信息：区域编号 -> 当前车辆数量
            /// </summary>
            public Dictionary<string, int> RegionVehicleCounts { get; set; } = new Dictionary<string, int>();

            /// <summary>
            /// 区域限制信息：区域编号 -> 最大允许车辆数
            /// </summary>
            public Dictionary<string, int> RegionMaxCounts { get; set; } = new Dictionary<string, int>();

            /// <summary>
            /// 被阻止的车辆统计：区域编号 -> 被阻止次数
            /// </summary>
            public Dictionary<string, int> BlockedCounts { get; set; } = new Dictionary<string, int>();
        }

        public override MissionStatus status { get; set; } = new RegionalTrafficControlMissionStatus();

        [JsonIgnore] private bool started = false;

        [JsonIgnore] private object sync = new object();

        /// <summary>
        /// 区域内的车辆记录：区域编号 -> 车辆ID列表
        /// </summary>
        [JsonIgnore] private readonly Dictionary<string, HashSet<int>> carsInRegions = new Dictionary<string, HashSet<int>>();

        /// <summary>
        /// 启动进程
        /// </summary>
        [MethodMember(Name = "启动进程", Description = "开始区域流量监控")]
        public override void Execute()
        {
            if (started)
            {
                Diagnosis.Post("区域流量监控已在运行中", "区域流量监控");
                return;
            }

            started = true;
            status.status = "运行中";

            // 订阅交通控制事件
            TrafficControl.BeforeLock += BeforeLockEvent;
            TrafficControl.AfterLeave += AfterLeaveEvent;
            TrafficControl.OnLockAcquired += OnLockAcquiredEvent;

            // 启动统计更新任务
            Task.Factory.StartNew(() =>
            {
                while (started)
                {
                    try
                    {
                        UpdateRegionStatistics();
                        Thread.Sleep(500);
                    }
                    catch (Exception e)
                    {
                        Diagnosis.Post($"{ExceptionFormatter.FormatEx(e)}", "区域流量监控");
                    }
                }
            });

            Diagnosis.Post("区域流量监控已启动", "区域流量监控", true);
        }

        /// <summary>
        /// 停止进程
        /// </summary>
        [MethodMember(Name = "停止进程", Description = "停止区域流量监控")]
        public void Stop()
        {
            if (!started)
            {
                return;
            }

            started = false;

            // 取消事件订阅
            TrafficControl.BeforeLock -= BeforeLockEvent;
            TrafficControl.AfterLeave -= AfterLeaveEvent;
            TrafficControl.OnLockAcquired -= OnLockAcquiredEvent;

            status.status = "已停止";
            Diagnosis.Post("区域流量监控已停止", "区域流量监控", true);
        }

        /// <summary>
        /// 获取站点的区域信息
        /// </summary>
        /// <param name="site">站点</param>
        /// <returns>区域标识和限制数量，如果站点不属于任何区域则返回null</returns>
        private (string regionId, int maxCount)? GetRegionInfo(Site site)
        {
            if (site == null || site.fields == null)
            {
                return null;
            }

            // 查找所有以Region开头的字段
            var regionField = site.fields.FirstOrDefault(kvp => kvp.Key.StartsWith("Region", StringComparison.OrdinalIgnoreCase));
            
            if (regionField.Key == null)
            {
                return null; // 站点不属于任何区域
            }

            string regionId = regionField.Key; // 例如 "Region1"
            
            // 字段值就是限制数量
            if (!int.TryParse(regionField.Value, out int maxCount))
            {
                return null; // 无法解析限制数量
            }

            return (regionId, maxCount);
        }

        /// <summary>
        /// 检查车辆是否已经在指定区域内
        /// </summary>
        private bool IsCarAlreadyInRegion(AbstractCar car, string regionId)
        {
            if (car?.status == null)
            {
                return false;
            }

            // 检查车辆当前占用的站点是否属于该区域
            if (car.status.holdingLocks != null)
            {
                foreach (var lockedSiteId in car.status.holdingLocks)
                {
                    var lockedSite = SimpleLib.GetSite(lockedSiteId);
                    var regionInfo = GetRegionInfo(lockedSite);
                    if (regionInfo.HasValue && regionInfo.Value.regionId == regionId)
                    {
                        return true; // 车辆已经在区域内
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// BeforeLock事件处理：检查车辆是否可以进入区域
        /// </summary>
        private bool BeforeLockEvent(AbstractCar car, int siteId)
        {
            try
            {
                var site = SimpleLib.GetSite(siteId);
                if (site == null)
                {
                    return true;
                }

                // 获取站点的区域信息
                var regionInfo = GetRegionInfo(site);
                if (!regionInfo.HasValue)
                {
                    return true; // 站点不属于任何区域，允许通过
                }

                var (regionId, maxCount) = regionInfo.Value;

                // 如果最大数量为0或负数，表示不限制
                if (maxCount <= 0)
                {
                    return true;
                }

                // 检查车辆是否已经在区域内
                lock (sync)
                {
                    if (IsCarAlreadyInRegion(car, regionId))
                    {
                        // 车辆已经在区域内，允许通行
                        return true;
                    }

                    // 车辆即将进入区域，需要检查是否超过限制
                    // 排除当前车辆本身，因为它还没有进入区域
                    int currentCount = CountCarsInRegion(regionId, excludeCarId: car.id);

                    // 如果当前车辆数量已达到或超过限制，阻止进入
                    if (currentCount >= maxCount)
                    {
                        var statusObj = (RegionalTrafficControlMissionStatus)status;
                        if (!statusObj.BlockedCounts.ContainsKey(regionId))
                        {
                            statusObj.BlockedCounts[regionId] = 0;
                        }
                        statusObj.BlockedCounts[regionId]++;

                        Diagnosis.Log($"车辆 {car.id} 尝试进入区域 {regionId} 被阻止，当前车辆数: {currentCount}/{maxCount}", "区域流量监控", true);
                        return false; // 阻止进入
                    }

                    return true; // 允许进入
                }
            }
            catch (Exception e)
            {
                Diagnosis.Post($"BeforeLockEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控");
                return true; // 发生错误时允许通过，避免阻塞系统
            }
        }

        /// <summary>
        /// AfterLeave事件处理：车辆离开区域时更新统计
        /// </summary>
        private void AfterLeaveEvent(AbstractCar car, int siteId)
        {
            try
            {
                var site = SimpleLib.GetSite(siteId);
                if (site == null)
                {
                    return;
                }

                // 获取站点的区域信息
                var regionInfo = GetRegionInfo(site);
                if (!regionInfo.HasValue)
                {
                    return; // 站点不属于任何区域
                }

                string regionId = regionInfo.Value.regionId;

                // 从区域车辆列表中移除该车辆
                lock (sync)
                {
                    if (carsInRegions.TryGetValue(regionId, out var carSet))
                    {
                        carSet.Remove(car.id);
                        if (carSet.Count == 0)
                        {
                            carsInRegions.Remove(regionId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Diagnosis.Post($"AfterLeaveEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控");
            }
        }

        /// <summary>
        /// OnLockAcquired事件处理：车辆成功锁定站点时，将其加入区域统计
        /// </summary>
        private void OnLockAcquiredEvent(AbstractCar car, int siteId)
        {
            try
            {
                var site = SimpleLib.GetSite(siteId);
                if (site == null)
                {
                    return;
                }

                // 获取站点的区域信息
                var regionInfo = GetRegionInfo(site);
                if (!regionInfo.HasValue)
                {
                    return; // 站点不属于任何区域
                }

                string regionId = regionInfo.Value.regionId;

                // 将车辆添加到区域车辆列表中
                lock (sync)
                {
                    if (!carsInRegions.TryGetValue(regionId, out var carSet))
                    {
                        carSet = new HashSet<int>();
                        carsInRegions[regionId] = carSet;
                    }
                    carSet.Add(car.id);
                }
            }
            catch (Exception e)
            {
                Diagnosis.Post($"OnLockAcquiredEvent错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控");
            }
        }

        /// <summary>
        /// 统计指定区域内的车辆数量
        /// </summary>
        /// <param name="regionId">区域标识</param>
        /// <param name="excludeCarId">要排除的车辆ID（可选，用于排除即将进入的车辆）</param>
        /// <returns>区域内的车辆数量</returns>
        private int CountCarsInRegion(string regionId, int excludeCarId = -1)
        {
            lock (sync)
            {
                // 首先从已记录的车辆列表中统计
                int count = 0;
                if (carsInRegions.TryGetValue(regionId, out var recordedCars))
                {
                    count = recordedCars.Count(carId => carId != excludeCarId);
                }

                // 同时检查所有站点，统计属于该区域且当前有车辆占用的站点
                var regionSites = SimpleLib.GetAllSites()
                    .Where(s =>
                    {
                        var regionInfo = GetRegionInfo(s);
                        return regionInfo.HasValue && regionInfo.Value.regionId == regionId;
                    })
                    .ToList();

                // 统计这些站点上的车辆（只统计已锁定的，不包括正在前往的）
                // 因为正在前往的车辆还没有真正进入区域
                var carsInRegionSites = SimpleLib.GetAllCars()
                    .OfType<Car>()
                    .Where(car =>
                    {
                        if (car?.status == null)
                            return false;

                        // 排除指定车辆
                        if (car.id == excludeCarId)
                            return false;

                        // 只统计已经在区域内的站点（holdingLocks）
                        // 不统计pendingLocks，因为那些车辆还没有真正进入区域
                        bool inRegionSite = car.status.holdingLocks?.Any(siteId =>
                        {
                            var site = SimpleLib.GetSite(siteId);
                            var regionInfo = GetRegionInfo(site);
                            return regionInfo.HasValue && regionInfo.Value.regionId == regionId;
                        }) == true;

                        return inRegionSite;
                    })
                    .Select(car => car.id)
                    .ToHashSet();

                // 返回两者中的较大值，确保统计准确
                return Math.Max(count, carsInRegionSites.Count);
            }
        }

        /// <summary>
        /// 更新区域统计信息
        /// </summary>
        private void UpdateRegionStatistics()
        {
            try
            {
                lock (sync)
                {
                    var statusObj = (RegionalTrafficControlMissionStatus)status;
                    statusObj.RegionVehicleCounts.Clear();
                    statusObj.RegionMaxCounts.Clear();

                    // 获取所有有区域字段的站点，按区域分组
                    var regionSites = SimpleLib.GetAllSites()
                        .Select(s =>
                        {
                            var regionInfo = GetRegionInfo(s);
                            return regionInfo.HasValue ? (site: s, regionId: regionInfo.Value.regionId, maxCount: regionInfo.Value.maxCount) : (site: (Site)null, regionId: (string)null, maxCount: 0);
                        })
                        .Where(x => x.site != null && !string.IsNullOrEmpty(x.regionId))
                        .GroupBy(x => x.regionId)
                        .ToList();

                    foreach (var group in regionSites)
                    {
                        string regionId = group.Key;
                        var firstItem = group.First();

                        // 获取最大允许数量（从第一个站点的字段值获取）
                        int maxCount = firstItem.maxCount;

                        // 统计当前车辆数量
                        int currentCount = CountCarsInRegion(regionId);

                        statusObj.RegionMaxCounts[regionId] = maxCount;
                        statusObj.RegionVehicleCounts[regionId] = currentCount;
                    }
                }
            }
            catch (Exception e)
            {
                Diagnosis.Post($"UpdateRegionStatistics错误: {ExceptionFormatter.FormatEx(e)}", "区域流量监控");
            }
        }
    }
}

