using System;
using System.Collections.Generic;
using System.Linq;
using SimpleCore.Library;

namespace StandardScene.ExtendDevice.Door
{
    /// <summary>
    /// 门状态枚举
    /// </summary>
    public enum DoorState
    {
        /// <summary>
        /// 关闭
        /// </summary>
        Closed = 0,

        /// <summary>
        /// 打开
        /// </summary>
        Open = 1,

        /// <summary>
        /// 未知状态
        /// </summary>
        Unknown = 2
    }

    /// <summary>
    /// 门控制器状态枚举
    /// </summary>
    public enum DoorControllerState
    {
        /// <summary>
        /// 离线
        /// </summary>
        Offline = 0,

        /// <summary>
        /// 在线
        /// </summary>
        Online = 1,

        /// <summary>
        /// 连接中
        /// </summary>
        Connecting = 2,

        /// <summary>
        /// 错误
        /// </summary>
        Error = 3
    }

    /// <summary>
    /// 基础门控制器类
    /// </summary>
    public abstract class BasicDoorController
    {
        /// <summary>
        /// 控制器索引
        /// </summary>
        public int Index { get; set; }

        /// <summary>
        /// IP地址
        /// </summary>
        public string Ip { get; set; } = string.Empty;

        /// <summary>
        /// 端口
        /// </summary>
        public int Port { get; set; } = 502;

        /// <summary>
        /// 控制器状态
        /// </summary>
        public DoorControllerState State { get; protected set; } = DoorControllerState.Offline;

        /// <summary>
        /// 是否在线
        /// </summary>
        public bool IsOnline => State == DoorControllerState.Online;

        /// <summary>
        /// 门状态字典，键为门索引
        /// </summary>
        public Dictionary<int, DoorState> DoorStates { get; protected set; } = new Dictionary<int, DoorState>();

        /// <summary>
        /// 门目标控制字典，键为门索引，值为期望的开关状态（true=打开，false=关闭）
        /// 仅作为指令缓存，实际通信由具体门控制器内部线程完成
        /// </summary>
        public Dictionary<int, bool> DoorControlTargets { get; protected set; } = new Dictionary<int, bool>();

        /// <summary>
        /// 门配置信息字典，键为门索引
        /// </summary>
        public Dictionary<int, DoorModel> DoorConfigs { get; protected set; } = new Dictionary<int, DoorModel>();

        /// <summary>
        /// 最后更新时间
        /// </summary>
        public DateTime LastUpdateTime { get; protected set; } = DateTime.Now;

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMessage { get; protected set; } = string.Empty;

        /// <summary>
        /// 更新控制器状态
        /// </summary>
        public virtual void UpdateState(DoorControllerState newState, string errorMessage = "")
        {
            State = newState;
            ErrorMessage = errorMessage;
            LastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 更新门状态
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <param name="state">门状态</param>
        public virtual void UpdateDoorState(int doorIndex, DoorState state)
        {
            if (!DoorStates.ContainsKey(doorIndex))
            {
                Diagnosis.Post($"门控制器{Index}不存在门{doorIndex}");
            }
            DoorStates[doorIndex] = state;
            LastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 获取门状态
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <returns>门状态，如果不存在则返回Unknown</returns>
        public virtual DoorState GetDoorState(int doorIndex)
        {
            return DoorStates.TryGetValue(doorIndex, out var state) ? state : DoorState.Unknown;
        }

        /// <summary>
        /// 初始化门状态
        /// </summary>
        /// <param name="doorIndices">门索引列表</param>
        public virtual void InitializeDoors(List<int> doorIndices)
        {
            DoorStates.Clear();
            DoorControlTargets.Clear();
            foreach (var index in doorIndices)
            {
                DoorStates[index] = DoorState.Closed;
                DoorControlTargets[index] = false;
            }
        }

        /// <summary>
        /// 初始化门配置信息
        /// </summary>
        /// <param name="doorConfigs">门配置列表</param>
        public virtual void InitializeDoorConfigs(List<DoorModel> doorConfigs)
        {
            DoorConfigs.Clear();
            if (doorConfigs != null)
            {
                foreach (var config in doorConfigs)
                {
                    DoorConfigs[config.Index] = new DoorModel
                    {
                        Index = config.Index,
                        ControlAddress = config.ControlAddress,
                        OpenStatusAddress = config.OpenStatusAddress,
                        NoControl = config.NoControl
                    };
                }
            }
        }

        /// <summary>
        /// 更新门配置信息
        /// </summary>
        /// <param name="doorConfigs">门配置列表</param>
        public virtual void UpdateDoorConfigs(List<DoorModel> doorConfigs)
        {
            if (doorConfigs == null)
            {
                DoorConfigs.Clear();
                return;
            }

            // 创建配置字典
            var configDict = doorConfigs.ToDictionary(d => d.Index);

            // 删除配置中不存在的门
            var toRemove = DoorConfigs.Keys.Where(k => !configDict.ContainsKey(k)).ToList();
            foreach (var key in toRemove)
            {
                DoorConfigs.Remove(key);
            }

            // 添加或更新门配置
            foreach (var config in doorConfigs)
            {
                DoorConfigs[config.Index] = new DoorModel
                {
                    Index = config.Index,
                    ControlAddress = config.ControlAddress,
                    OpenStatusAddress = config.OpenStatusAddress,
                    NoControl = config.NoControl
                };
            }
        }

        /// <summary>
        /// 获取门配置信息
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <returns>门配置信息，如果不存在则返回null</returns>
        public virtual DoorModel GetDoorConfig(int doorIndex)
        {
            return DoorConfigs.TryGetValue(doorIndex, out var config) ? config : null;
        }

        /// <summary>
        /// 设置门的目标控制状态（仅修改内存字段，不直接进行通信）
        /// 实际的通信写入由具体门控制器在内部线程中根据该目标状态执行
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <param name="open">true=打开，false=关闭</param>
        public virtual void SetDoorControlTarget(int doorIndex, bool open)
        {
            // 统一支持 NoControl：当门被配置为不允许发送任何控制指令时，
            // 强制将目标置为 false，并避免为其它控制器留下“需要开门”的目标。
            if (DoorConfigs.TryGetValue(doorIndex, out var cfg) && cfg != null && cfg.NoControl)
            {
                DoorControlTargets[doorIndex] = false;
                LastUpdateTime = DateTime.Now;
                return;
            }
            DoorControlTargets[doorIndex] = open;
            LastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 连接门控制器
        /// </summary>
        public virtual void Connect()
        {
            UpdateState(DoorControllerState.Connecting);
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public virtual void Disconnect()
        {
            UpdateState(DoorControllerState.Offline);
        }

        /// <summary>
        /// 读取门状态（开到位信号）
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <returns>门状态</returns>
        public abstract bool ReadDoorState(int doorIndex);

        /// <summary>
        /// 写入门控制信号（开关控制）
        /// </summary>
        /// <param name="doorIndex">门索引</param>
        /// <param name="open">true=打开，false=关闭</param>
        public abstract void WriteDoorControl(int doorIndex, bool open);
    }
}
