using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Mapster;
using Microsoft.Extensions.Logging;
using NPP.SmartSchedue.Api.Contracts.Services.Equipment;
using NPP.SmartSchedue.Api.Contracts.Services.Equipment.Dto;
using NPP.SmartSchedue.Api.Contracts.Domain.Equipment;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;

namespace NPP.SmartSchedue.Api.Services.Equipment;

/// <summary>
/// 设备本地服务实现（专用于SmartSchedule模块）
/// 提供设备信息的本地化查询功能，避免跨服务调用
/// </summary>
public class EquipmentLocalService : BaseService, IEquipmentLocalService, IDynamicApi
{
    private readonly IEquipmentRepository _equipmentRepository;
    private readonly IEquipmentMaintenanceRepository _maintenanceRepository;
    private readonly IEquipmentCalibrationRepository _calibrationRepository;
    private readonly ILogger<EquipmentLocalService> _logger;

    public EquipmentLocalService(
        IEquipmentRepository equipmentRepository,
        IEquipmentMaintenanceRepository maintenanceRepository,
        IEquipmentCalibrationRepository calibrationRepository,
        ILogger<EquipmentLocalService> logger)
    {
        _equipmentRepository = equipmentRepository;
        _maintenanceRepository = maintenanceRepository;
        _calibrationRepository = calibrationRepository;
        _logger = logger;
    }

    /// <summary>
    /// 获取设备列表
    /// </summary>
    public async Task<List<EquipmentListOutput>> GetListAsync(GetEquipmentListInput input)
    {
        try
        {
            var query = _equipmentRepository.Select;

            // 应用查询条件
            if (!string.IsNullOrEmpty(input.EquipmentType))
            {
                query = query.Where(e => e.EquipmentType == input.EquipmentType);
            }

            if (input.Status.HasValue)
            {
                query = query.Where(e => e.Status == input.Status.Value);
            }

            if (!string.IsNullOrEmpty(input.Name))
            {
                query = query.Where(e => e.Name.Contains(input.Name));
            }

            if (!string.IsNullOrEmpty(input.InternalNumber))
            {
                query = query.Where(e => e.InternalNumber.Contains(input.InternalNumber));
            }

            if (input.ResponsiblePersonId.HasValue)
            {
                query = query.Where(e => e.ResponsiblePersonId == input.ResponsiblePersonId.Value);
            }

            if (input.ProcessID.HasValue)
            {
                query = query.Where(e => e.ProcessID == input.ProcessID.Value);
            }

            var entities = await query.ToListAsync();
            var result = entities.Adapt<List<EquipmentListOutput>>();

            // 填充维护和校验日期信息
            foreach (var item in result)
            {
                await FillMaintenanceAndCalibrationDatesAsync(item);
            }

            _logger.LogInformation("成功获取设备列表，数量: {Count}", result.Count);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取设备列表时发生异常");
            throw;
        }
    }

    /// <summary>
    /// 获取设备详情
    /// </summary>
    public async Task<EquipmentListOutput> GetAsync(long id)
    {
        try
        {
            var entity = await _equipmentRepository.GetAsync(id);
            if (entity == null)
            {
                _logger.LogWarning("设备不存在，ID: {Id}", id);
                return null;
            }

            var result = entity.Adapt<EquipmentListOutput>();
            await FillMaintenanceAndCalibrationDatesAsync(result);

            _logger.LogInformation("成功获取设备详情，ID: {Id}", id);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取设备详情时发生异常，ID: {Id}", id);
            throw;
        }
    }

    /// <summary>
    /// 获取可用设备列表
    /// </summary>
    public async Task<List<EquipmentListOutput>> GetAvailableEquipmentAsync(DateTime date, long? processId = null)
    {
        try
        {
            var query = _equipmentRepository.Select.Where(e => e.Status == EquipmentStatus.Normal);

            // 如果指定了工序，过滤适配的设备
            if (processId.HasValue)
            {
                query = query.Where(e => e.ProcessID == processId.Value);
            }

            var entities = await query.ToListAsync();
            var result = new List<EquipmentListOutput>();

            foreach (var entity in entities)
            {
                var equipment = entity.Adapt<EquipmentListOutput>();
                await FillMaintenanceAndCalibrationDatesAsync(equipment);

                // 检查设备在指定日期是否可用
                if (IsEquipmentAvailableForDate(equipment, date))
                {
                    result.Add(equipment);
                }
            }

            _logger.LogInformation("成功获取可用设备列表，日期: {Date}, 工序ID: {ProcessId}, 数量: {Count}", 
                date, processId, result.Count);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取可用设备列表时发生异常，日期: {Date}, 工序ID: {ProcessId}", date, processId);
            throw;
        }
    }

    /// <summary>
    /// 检查设备是否可用
    /// </summary>
    public async Task<bool> IsEquipmentAvailableAsync(long equipmentId, DateTime date)
    {
        try
        {
            var equipment = await GetAsync(equipmentId);
            if (equipment == null)
            {
                return false;
            }

            var isAvailable = IsEquipmentAvailableForDate(equipment, date);
            _logger.LogInformation("设备可用性检查完成，设备ID: {EquipmentId}, 日期: {Date}, 可用: {Available}", 
                equipmentId, date, isAvailable);
            return isAvailable;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "检查设备可用性时发生异常，设备ID: {EquipmentId}, 日期: {Date}", equipmentId, date);
            return false; // 保守策略：异常时返回不可用
        }
    }

    /// <summary>
    /// 获取需要维护的设备列表
    /// </summary>
    public async Task<List<EquipmentListOutput>> GetNeedMaintenanceAsync(DateTime date)
    {
        try
        {
            var equipmentIds = await _maintenanceRepository.GetMaintenanceEquipmentIdsAsync(date);
            var result = new List<EquipmentListOutput>();

            foreach (var equipmentId in equipmentIds)
            {
                var equipment = await GetAsync(equipmentId);
                if (equipment != null && IsMaintenanceNeededOnDate(equipment, date))
                {
                    result.Add(equipment);
                }
            }

            _logger.LogInformation("成功获取需要维护的设备列表，日期: {Date}, 数量: {Count}", date, result.Count);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取需要维护的设备列表时发生异常，日期: {Date}", date);
            return new List<EquipmentListOutput>();
        }
    }

    /// <summary>
    /// 获取需要校验的设备列表
    /// </summary>
    public async Task<List<EquipmentListOutput>> GetNeedCalibrationAsync(DateTime date)
    {
        try
        {
            var equipmentIds = await _calibrationRepository.GetCalibrationEquipmentIdsAsync(date);
            var result = new List<EquipmentListOutput>();

            foreach (var equipmentId in equipmentIds)
            {
                var equipment = await GetAsync(equipmentId);
                if (equipment != null && IsCalibrationNeededOnDate(equipment, date))
                {
                    result.Add(equipment);
                }
            }

            _logger.LogInformation("成功获取需要校验的设备列表，日期: {Date}, 数量: {Count}", date, result.Count);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取需要校验的设备列表时发生异常，日期: {Date}", date);
            return new List<EquipmentListOutput>();
        }
    }

    /// <summary>
    /// 批量检查设备可用性
    /// </summary>
    public async Task<Dictionary<long, bool>> BatchCheckEquipmentAvailabilityAsync(List<long> equipmentIds, DateTime date)
    {
        try
        {
            _logger.LogInformation("批量检查设备可用性，设备数量: {Count}, 日期: {Date}", equipmentIds.Count, date);

            var result = new Dictionary<long, bool>();
            var tasks = equipmentIds.Select(async equipmentId =>
            {
                var isAvailable = await IsEquipmentAvailableAsync(equipmentId, date);
                return new { EquipmentId = equipmentId, IsAvailable = isAvailable };
            });

            var results = await Task.WhenAll(tasks);

            foreach (var item in results)
            {
                result[item.EquipmentId] = item.IsAvailable;
            }

            _logger.LogInformation("批量检查设备可用性完成");
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "批量检查设备可用性时发生异常");
            // 保守策略：所有设备都标记为不可用
            return equipmentIds.ToDictionary(id => id, _ => false);
        }
    }

    #region 私有辅助方法

    /// <summary>
    /// 填充维护和校验日期信息
    /// </summary>
    private async Task FillMaintenanceAndCalibrationDatesAsync(EquipmentListOutput equipment)
    {
        try
        {
            // 获取最新的维护记录
            var maintenanceRecords = await _maintenanceRepository.GetByEquipmentIdAsync(equipment.Id);
            if (maintenanceRecords != null && maintenanceRecords.Count > 0)
            {
                var lastMaintenance = maintenanceRecords
                    .Where(m => m.Status == MaintenanceStatus.Completed)
                    .OrderByDescending(m => m.MaintenanceDate)
                    .FirstOrDefault();

                if (lastMaintenance != null)
                {
                    equipment.LastMaintenanceDate = lastMaintenance.MaintenanceDate;
                    equipment.NextMaintenanceDate = lastMaintenance.NextPlannedDate;
                }
            }

            // 获取最新的校验记录
            var calibrationRecords = await _calibrationRepository.GetByEquipmentIdAsync(equipment.Id);
            if (calibrationRecords != null && calibrationRecords.Count > 0)
            {
                var lastCalibration = calibrationRecords
                    .Where(c => c.Status == CalibrationStatus.Completed)
                    .OrderByDescending(c => c.CalibrationDate)
                    .FirstOrDefault();

                if (lastCalibration != null)
                {
                    equipment.LastCalibrationDate = lastCalibration.CalibrationDate;
                    equipment.NextCalibrationDate = lastCalibration.NextPlannedDate;
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "填充设备维护和校验日期信息时发生异常，设备ID: {EquipmentId}", equipment.Id);
        }
    }

    /// <summary>
    /// 检查设备在指定日期是否可用
    /// </summary>
    private bool IsEquipmentAvailableForDate(EquipmentListOutput equipment, DateTime date)
    {
        // 基本状态检查：只有正常状态的设备才可用
        if (equipment.Status != EquipmentStatus.Normal)
        {
            return false;
        }

        // 维护日期检查：如果指定日期需要维护，则不可用
        if (equipment.NextMaintenanceDate.HasValue && 
            equipment.NextMaintenanceDate.Value.Date == date.Date)
        {
            return false;
        }

        // 校验日期检查：如果指定日期需要校验，则不可用
        if (equipment.NextCalibrationDate.HasValue && 
            equipment.NextCalibrationDate.Value.Date == date.Date)
        {
            return false;
        }

        return true;
    }

    /// <summary>
    /// 检查设备是否需要在指定日期进行维护
    /// </summary>
    private bool IsMaintenanceNeededOnDate(EquipmentListOutput equipment, DateTime date)
    {
        return equipment.NextMaintenanceDate.HasValue && 
               equipment.NextMaintenanceDate.Value.Date == date.Date;
    }

    /// <summary>
    /// 检查设备是否需要在指定日期进行校验
    /// </summary>
    private bool IsCalibrationNeededOnDate(EquipmentListOutput equipment, DateTime date)
    {
        return equipment.NextCalibrationDate.HasValue && 
               equipment.NextCalibrationDate.Value.Date == date.Date;
    }

    #endregion
}