using System;
using System.Collections.Generic;
using System.Linq;
using CncService.Interface;
using CncModels.Dto;
using CncModels.Dto.Machine;
using CncModels.Dto.Worker;
using CncModels.Entity;
using CncModels.Constants;
using CncRepository.Interface;

namespace CncService.Impl
{
    /// <summary>
    /// 员工管理实现
    /// </summary>
    public class WorkerService : IWorkerService
    {
        private readonly IWorkerRepository _workerRepository;
        private readonly IWorkerMachineRepository _workerMachineRepository;
        private readonly IMachineRepository _machineRepository;
        private readonly ISysConfigRepository _sysConfigRepository;

        public WorkerService(
            IWorkerRepository workerRepository,
            IWorkerMachineRepository workerMachineRepository,
            IMachineRepository machineRepository,
            ISysConfigRepository sysConfigRepository)
        {
            _workerRepository = workerRepository ?? throw new ArgumentNullException(nameof(workerRepository));
            _workerMachineRepository = workerMachineRepository ?? throw new ArgumentNullException(nameof(_workerMachineRepository));
            _machineRepository = machineRepository ?? throw new ArgumentNullException(nameof(machineRepository));
            _sysConfigRepository = sysConfigRepository ?? throw new ArgumentNullException(nameof(sysConfigRepository));
        }

        /// <summary>从sys_config读取在线超时阈值（秒）</summary>
        private int GetOnlineTimeout()
        {
            var cfg = _sysConfigRepository.GetByKey("online_timeout");
            if (cfg != null && int.TryParse(cfg.ConfigValue, out var val) && val > 0) return val;
            return 300;
        }

        /// <inheritdoc/>
        public PagedResult<WorkerListItem> GetList(WorkerQuery query)
        {
            if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
            return _workerRepository.GetList(query);
        }

        /// <inheritdoc/>
        public WorkerDetailResponse GetById(int id)
        {
            if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            var w = _workerRepository.GetById(id);
            if (w == null) throw new BusinessException(ErrorCode.NotFound, "员工未找到");

            var bindings = _workerMachineRepository.GetByWorkerId(id);
            var machineNames = new List<string>();
            foreach (var b in bindings)
            {
                var m = _machineRepository.GetById(b.MachineId);
                if (m != null) machineNames.Add(m.Name ?? m.DeviceCode);
            }

            return new WorkerDetailResponse
            {
                Id = w.Id,
                Code = w.Code,
                Name = w.Name,
                IsEnabled = w.IsEnabled == 1,
                MachineCount = bindings.Count,
                MachineNames = string.Join(", ", machineNames)
            };
        }

        /// <inheritdoc/>
        public int Create(CreateWorkerRequest request)
        {
            if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
            if (string.IsNullOrWhiteSpace(request.Code)) throw new BusinessException(ErrorCode.BadRequest, "工号不能为空");
            // 唯一性校验
            var existing = _workerRepository.GetByCode(request.Code);
            if (existing != null) throw new BusinessException(ErrorCode.Conflict, "工号已存在");

            var entity = new Worker
            {
                Name = request.Name,
                Code = request.Code,
                IsEnabled = 1,
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            };
            var workerId = _workerRepository.Create(entity);

            // 绑定机床
            if (request.MachineIds != null)
            {
                foreach (var mid in request.MachineIds)
                {
                    var binding = _workerMachineRepository.GetByMachineId(mid);
                    if (binding != null) throw new BusinessException(ErrorCode.Conflict, $"机床(ID={mid})已绑定其他工人");
                    _workerMachineRepository.Create(workerId, mid);
                }
            }
            return workerId;
        }

        /// <inheritdoc/>
        public bool Update(int id, UpdateWorkerRequest request)
        {
            if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
            var entity = _workerRepository.GetById(id);
            if (entity == null) throw new BusinessException(ErrorCode.NotFound, "员工未找到");

            entity.Name = request.Name ?? entity.Name;
            if (!string.IsNullOrWhiteSpace(request.Code) && request.Code != entity.Code)
            {
                var dup = _workerRepository.GetByCode(request.Code);
                if (dup != null) throw new BusinessException(ErrorCode.Conflict, "工号已存在");
                entity.Code = request.Code;
            }
            entity.UpdatedAt = DateTime.Now;
            _workerRepository.Update(entity);

            // 全量替换机床绑定
            if (request.MachineIds != null)
            {
                _workerMachineRepository.DeleteByWorkerId(id);
                foreach (var mid in request.MachineIds)
                {
                    var binding = _workerMachineRepository.GetByMachineId(mid);
                    if (binding != null) throw new BusinessException(ErrorCode.Conflict, $"机床(ID={mid})已绑定其他工人");
                    _workerMachineRepository.Create(id, mid);
                }
            }
            return true;
        }

        /// <inheritdoc/>
        public bool Delete(int id)
        {
            if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            // 解绑所有机床
            _workerMachineRepository.DeleteByWorkerId(id);
            return _workerRepository.Delete(id);
        }

        /// <inheritdoc/>
        public int BatchDelete(List<int> ids)
        {
            if (ids == null || ids.Count == 0) throw new BusinessException(ErrorCode.BadRequest, "请选择要删除的员工");
            // 先解绑所有机床
            foreach (var id in ids)
            {
                _workerMachineRepository.DeleteByWorkerId(id);
            }
            return _workerRepository.BatchDelete(ids);
        }

        /// <inheritdoc/>
        public bool ToggleEnabled(int id)
        {
            if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            return _workerRepository.ToggleEnabled(id);
        }

        /// <inheritdoc/>
        public bool BindMachine(int workerId, int machineId)
        {
            if (workerId <= 0 || machineId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的参数");
            // 检查是否已绑定
            var existing = _workerMachineRepository.GetByMachineId(machineId);
            if (existing != null) throw new BusinessException(ErrorCode.Conflict, "该机床已绑定其他工人");
            _workerMachineRepository.Create(workerId, machineId);
            return true;
        }

        /// <inheritdoc/>
        public bool UnbindMachine(int workerId, int machineId)
        {
            if (workerId <= 0 || machineId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的参数");
            return _workerMachineRepository.DeleteByMachineId(machineId);
        }

        /// <inheritdoc/>
        public List<WorkerMachineItem> GetMachines(int workerId)
        {
            if (workerId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            var bindings = _workerMachineRepository.GetByWorkerId(workerId);
            var result = new List<WorkerMachineItem>();
            foreach (var b in bindings)
            {
                var m = _machineRepository.GetById(b.MachineId);
                if (m == null) continue;
                string workshopName = null;
                string brandName = null;
                // 车间名称需查关联表，但当前简单返回null即可
                result.Add(new WorkerMachineItem
                {
                    MachineId = m.Id,
                    MachineName = m.Name ?? m.DeviceCode,
                    DeviceCode = m.DeviceCode,
                    WorkshopName = workshopName,
                    BrandName = brandName,
                    IsOnline = m.IsEnabled == 1 && m.LastPingTime.HasValue && (DateTime.Now - m.LastPingTime.Value).TotalSeconds <= GetOnlineTimeout(),
                    ProgramName = m.LastProgramName
                });
            }
            return result;
        }

        /// <inheritdoc/>
        public List<WorkerTodayProdItem> GetTodayProduction(int workerId)
        {
            if (workerId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            // 采集服务未运行，返回空列表
            return new List<WorkerTodayProdItem>();
        }

        /// <inheritdoc/>
        public List<WorkerTrendItem> GetProductionTrend(int workerId)
        {
            if (workerId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
            // 采集服务未运行，返回7天空数据
            var result = new List<WorkerTrendItem>();
            for (int i = 6; i >= 0; i--)
            {
                result.Add(new WorkerTrendItem
                {
                    Date = DateTime.Today.AddDays(-i).ToString("yyyy-MM-dd"),
                    Quantity = 0
                });
            }
            return result;
        }

        /// <inheritdoc/>
        public List<WorkerAvailableMachineItem> GetAvailableMachines()
        {
            // 获取所有机床（不限在线状态），排除已绑定的
            var allMachines = _machineRepository.GetList(new MachineQuery { PageSize = 9999 }).Items;
            var result = new List<WorkerAvailableMachineItem>();
            foreach (var m in allMachines)
            {
                var binding = _workerMachineRepository.GetByMachineId(m.Id);
                if (binding == null)
                {
                    result.Add(new WorkerAvailableMachineItem
                    {
                        Id = m.Id,
                        Name = m.Name ?? m.DeviceCode,
                        DeviceCode = m.DeviceCode
                    });
                }
            }
            return result;
        }
    }
}
