using Common.Attributes;
using Model.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using DeviceCommand.Base;
using DeviceCommand.Devices;
using System.ComponentModel;

namespace DeviceCommand.Devices
{
    /// <summary>
    /// 系统控制功能类型枚举 (中文)
    /// </summary>
    public enum 功能动作 : byte
    {
        单相充电,
        抛负载,
        短路测试,
        蜂鸣器报警
    }

    /// <summary>
    /// 精简后的 IO 端口信息结构体
    /// </summary>
    public struct IoPortInfo
    {
        public int ModuleIndex { get; set; }   // IO板卡/模块序号 (1 或 2)
        public ushort Address { get; set; }    // 转换为 Modbus 的线圈相对偏移地址 (Y1->0, Y2->1)

        public IoPortInfo(int moduleIndex, ushort address)
        {
            ModuleIndex = moduleIndex;
            Address = address;
        }
    }

    [ACPCommand]
    public class IOBoardGroup
    {
        // 声明底层的 2 个 IO 板卡实例
        public IOBoard Board1 { get; private set; }
        public IOBoard Board2 { get; private set; }

        private readonly byte _slaveAddress = 1; // 默认 Modbus 从站号为 1

        // 核心：严格对齐图片数据的双层嵌套配置字典 (2个模块，1-8台架)
        private static readonly Dictionary<int, Dictionary<功能动作, IoPortInfo>> IoMapping
            = new Dictionary<int, Dictionary<功能动作, IoPortInfo>>()
        {
            { 1, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(1, 5) }, // Y6 -> 5
                { 功能动作.抛负载,         new IoPortInfo(1, 0) }, // Y1 -> 0
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 15) }  // Y9 -> 8
            }},
            { 2, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(1, 6) }, // Y7 -> 6
                { 功能动作.抛负载,         new IoPortInfo(1, 2) }, // Y3 -> 2
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 14) }  // Y10 -> 9
            }},
            { 3, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(1, 7) }, // Y8 -> 7
                { 功能动作.抛负载,         new IoPortInfo(1, 3) }, // Y4 -> 3
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 13) } // Y11 -> 10
            }},
            { 4, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(1, 8) }, // Y9 -> 8
                { 功能动作.抛负载,         new IoPortInfo(1, 4) }, // Y5 -> 4
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 12) } // Y12 -> 11
            }},
            { 5, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(2, 4) }, // Y5 -> 4
                { 功能动作.抛负载,         new IoPortInfo(2, 0) }, // Y1 -> 0
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 11) } // Y13 -> 12
            }},
            { 6, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(2, 5) }, // Y6 -> 5
                { 功能动作.抛负载,         new IoPortInfo(2, 1) }, // Y2 -> 1
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 10) } // Y14 -> 13
            }},
            { 7, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(2, 6) }, // Y7 -> 6
                { 功能动作.抛负载,         new IoPortInfo(2, 2) }, // Y3 -> 2
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 9) } // Y15 -> 14
            }},
            { 8, new Dictionary<功能动作, IoPortInfo> {
                { 功能动作.单相充电,       new IoPortInfo(2, 7) }, // Y8 -> 7
                { 功能动作.抛负载,         new IoPortInfo(2, 3) }, // Y4 -> 3
                { 功能动作.短路测试,       new IoPortInfo(1, 1) }, // Y2 -> 1
                { 功能动作.蜂鸣器报警,     new IoPortInfo(2, 8) } // Y16 -> 15
            }}
        };

        public IOBoardGroup(IOBoard board1, IOBoard board2)
        {
            Board1 = board1 ?? throw new ArgumentNullException(nameof(board1), "IOBoard Board1 实例不能为空。");
            Board2 = board2 ?? throw new ArgumentNullException(nameof(board2), "IOBoard Board2 实例不能为空。");
        }



        /// <summary>
        /// 执行指定台架的功能动作控制（带高低电平开关及底层安全互锁）
        /// </summary>
        /// <param name="台架序号">台架/工位序号 (1 - 8)</param>
        /// <param name="动作">控制功能类型 (单相充电, 抛负载, 短路测试, 蜂鸣器报警)</param>
        /// <param name="开关状态">开关状态 (true: 开启吸合, false: 关闭断开)</param>
        /// <param name="取消令牌">异步取消令牌</param>
        public async Task 执行台架动作Async(int 台架序号, 功能动作 动作, bool 开关状态, CancellationToken 取消令牌 = default)
        {
            // 1. 根据传入的台架序号和动作检索字典映射关系
            if (!IoMapping.TryGetValue(台架序号, out var 动作字典) || !动作字典.TryGetValue(动作, out var io信息))
            {
                throw new ArgumentException($"未找到台架 [{台架序号}] 对应功能 [{动作}] 的 IO 点位映射配置。");
            }

            // 2. 软件防错高危互锁逻辑
            if (开关状态)
            {
                if (动作 == 功能动作.单相充电)
                {
                    var 短路点位 = IoMapping[台架序号][功能动作.短路测试];
                    await GetBoardInstance(短路点位.ModuleIndex).写输出开关(_slaveAddress, 短路点位.Address, false);
                }
                else if (动作 == 功能动作.短路测试)
                {
                    var 充电点位 = IoMapping[台架序号][功能动作.单相充电];
                    await GetBoardInstance(充电点位.ModuleIndex).写输出开关(_slaveAddress, 充电点位.Address, false);
                }
            }

            // 3. 动态获取目标板卡实例并直接驱动开关端口
            IOBoard 目标板卡 = GetBoardInstance(io信息.ModuleIndex);
            await 目标板卡.写输出开关(_slaveAddress, io信息.Address, 开关状态);
        }

        /// <summary>
        /// 内部路由辅助方法：根据板卡索引安全获取当前连接的实例对象
        /// </summary>
        private IOBoard GetBoardInstance(int moduleIndex)
        {
            IOBoard board = moduleIndex switch
            {
                1 => Board1,
                2 => Board2,
                _ => throw new ArgumentOutOfRangeException(nameof(moduleIndex), "非法的板卡序号，系统仅支持 1# 和 2# 模块。")
            };

            return board ?? throw new InvalidOperationException($"IO板卡模块 [{moduleIndex}#] 尚未完成初始化，无法建立总线通信。");
        }
    }
}