using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using NPP.SmartSchedue.Api.Contracts.Services.Time;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Output;
using NPP.SmartSchedue.Api.Repositories.Time;
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using Microsoft.Extensions.Logging;

namespace NPP.SmartSchedue.Api.Services.Time;

/// <summary>
/// 班次规则映射服务
/// </summary>
[DynamicApi(Area = "app")]
public class ShiftRuleMappingService : BaseService, IShiftRuleMappingService, IDynamicApi
{
    private readonly ShiftRuleMappingRepository _shiftRuleMappingRepository;
    private readonly ShiftRepository _shiftRepository;
    private readonly ShiftRuleRepository _shiftRuleRepository;
    private readonly ILogger<ShiftRuleMappingService> _logger;

    public ShiftRuleMappingService(
        ShiftRuleMappingRepository shiftRuleMappingRepository,
        ShiftRepository shiftRepository,
        ShiftRuleRepository shiftRuleRepository,
        ILogger<ShiftRuleMappingService> logger)
    {
        _shiftRuleMappingRepository = shiftRuleMappingRepository;
        _shiftRepository = shiftRepository;
        _shiftRuleRepository = shiftRuleRepository;
        _logger = logger;
    }

    /// <summary>
    /// 查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<ShiftRuleMappingGetOutput> GetAsync(long id)
    {
        var output = await _shiftRuleMappingRepository.Select
            .WhereDynamic(id)
            .ToOneAsync<ShiftRuleMappingGetOutput>();

        return output;
    }

    /// <summary>
    /// 查询分页
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<PageOutput<ShiftRuleMappingGetPageOutput>> GetPageAsync(PageInput<ShiftRuleMappingGetPageInput> input)
    {
        var list = await _shiftRuleMappingRepository.Select
            .WhereIf(input.Filter?.ShiftId.HasValue == true, a => a.ShiftId == input.Filter.ShiftId.Value)
            .WhereIf(input.Filter?.RuleId.HasValue == true, a => a.RuleId == input.Filter.RuleId.Value)
            .WhereIf(input.Filter?.IsEnabled.HasValue == true, a => a.IsEnabled == input.Filter.IsEnabled.Value)
            .Count(out var total)
            .OrderByDescending(a => a.Id)
            .Page(input.CurrentPage, input.PageSize)
            .ToListAsync<ShiftRuleMappingGetPageOutput>();

        var data = new PageOutput<ShiftRuleMappingGetPageOutput>()
        {
            List = list,
            Total = total
        };

        return data;
    }

    /// <summary>
    /// 根据班次查询映射的规则
    /// </summary>
    /// <param name="shiftId">班次ID</param>
    /// <returns>映射的规则列表</returns>
    [HttpGet]
    public async Task<List<ShiftRuleMappingGetOutput>> GetRulesByShiftIdAsync(long shiftId)
    {
        var list = await _shiftRuleMappingRepository.Select
            .Where(a => a.ShiftId == shiftId)
            .OrderBy(a => a.ExecutionPriority)
            .OrderBy(a => a.Id)
            .ToListAsync<ShiftRuleMappingGetOutput>();

        _logger.LogInformation($"查询班次{shiftId}的规则映射，共{list.Count}条");
        
        return list;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<long> AddAsync(ShiftRuleMappingAddInput input)
    {

        try
        {


            // 验证班次是否存在
            var shiftExists = await _shiftRepository.Select
                .Where(x => x.Id == input.ShiftId)
                .AnyAsync();

            if (!shiftExists)
            {
                throw new Exception($"班次不存在: {input.ShiftId}");
            }

            // 验证规则是否存在
            var ruleExists = await _shiftRuleRepository.Select
                .Where(x => x.Id == input.RuleId)
                .AnyAsync();

            if (!ruleExists)
            {
                throw new Exception($"班次规则不存在: {input.RuleId}");
            }

            // 检查是否已存在相同的映射
            var existingMapping = await _shiftRuleMappingRepository.Select
                .Where(x => x.ShiftId == input.ShiftId && x.RuleId == input.RuleId)
                .FirstAsync();

            if (existingMapping != null)
            {
                throw new Exception($"班次已经关联了该规则");
            }

            var entity = Mapper.Map<ShiftRuleMappingEntity>(input);
            var result = await _shiftRuleMappingRepository.InsertAsync(entity);
            return result.Id;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

        return 0;
    }

    /// <summary>
    /// 班次增加规则
    /// </summary>
    /// <param name="shiftId">班次ID</param>
    /// <param name="ruleId">规则ID</param>
    /// <param name="input">映射配置</param>
    /// <returns>映射ID</returns>
    [HttpPost]
    public async Task<long> AddRuleToShiftAsync(long shiftId, long ruleId, ShiftRuleMappingAddInput input)
    {
        // 验证班次是否存在A
        var shiftExists = await _shiftRepository.Select
            .Where(x => x.Id == shiftId)
            .AnyAsync();
            
        if (!shiftExists)
        {
            throw new Exception($"班次不存在: {shiftId}");
        }
        
        // 验证规则是否存在
        var ruleExists = await _shiftRuleRepository.Select
            .Where(x => x.Id == ruleId)
            .AnyAsync();
            
        if (!ruleExists)
        {
            throw new Exception($"班次规则不存在: {ruleId}");
        }
        
        // 检查是否已存在相同的映射
        var existingMapping = await _shiftRuleMappingRepository.Select
            .Where(x => x.ShiftId == shiftId && x.RuleId == ruleId)
            .FirstAsync();
            
        if (existingMapping != null)
        {
            throw new Exception($"班次已经关联了该规则");
        }

        var entity = Mapper.Map<ShiftRuleMappingEntity>(input);
        entity.ShiftId = shiftId;
        entity.RuleId = ruleId;
        
        var result = await _shiftRuleMappingRepository.InsertAsync(entity);
        return result.Id;
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task UpdateAsync(ShiftRuleMappingUpdateInput input)
    {
        var entity = await _shiftRuleMappingRepository.GetAsync(input.Id);
        Mapper.Map(input, entity);
        await _shiftRuleMappingRepository.UpdateAsync(entity);
    }

    /// <summary>
    /// 班次修改规则
    /// </summary>
    /// <param name="mappingId">映射ID</param>
    /// <param name="input">修改信息</param>
    /// <returns>操作结果</returns>
    [HttpPut]
    public async Task UpdateShiftRuleAsync(long mappingId, ShiftRuleMappingUpdateInput input)
    {
        var entity = await _shiftRuleMappingRepository.GetAsync(mappingId);
        if (entity == null)
        {
            throw new Exception($"班次规则映射不存在: {mappingId}");
        }

        // 如果修改了规则ID，需要验证新规则是否存在
        if (input.RuleId != entity.RuleId)
        {
            var ruleExists = await _shiftRuleRepository.Select
                .Where(x => x.Id == input.RuleId)
                .AnyAsync();
                
            if (!ruleExists)
            {
                throw new Exception($"班次规则不存在: {input.RuleId}");
            }
            
            // 检查是否与其他映射冲突
            var existingMapping = await _shiftRuleMappingRepository.Select
                .Where(x => x.ShiftId == entity.ShiftId && x.RuleId == input.RuleId && x.Id != mappingId)
                .FirstAsync();
                
            if (existingMapping != null)
            {
                throw new Exception("班次已经关联了该规则");
            }
        }

        Mapper.Map(input, entity);
        await _shiftRuleMappingRepository.UpdateAsync(entity);
        
        _logger.LogInformation($"更新班次规则映射成功: ID {mappingId}");
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task DeleteAsync(long id)
    {
        await _shiftRuleMappingRepository.DeleteAsync(id);
    }

    /// <summary>
    /// 软删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task SoftDeleteAsync(long id)
    {
        await _shiftRuleMappingRepository.SoftDeleteAsync(id);
    }

    /// <summary>
    /// 批量软删除
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task BatchSoftDeleteAsync(long[] ids)
    {
        await _shiftRuleMappingRepository.SoftDeleteAsync(ids);
    }

    /// <summary>
    /// 班次删除规则
    /// </summary>
    /// <param name="shiftId">班次ID</param>
    /// <param name="ruleId">规则ID</param>
    /// <returns>操作结果</returns>
    [HttpDelete]
    public async Task RemoveRuleFromShiftAsync(long shiftId, long ruleId)
    {
        var entity = await _shiftRuleMappingRepository.Select
            .Where(x => x.ShiftId == shiftId && x.RuleId == ruleId)
            .FirstAsync();
            
        if (entity == null)
        {
            throw new Exception($"未找到班次{shiftId}和规则{ruleId}的映射关系");
        }
        
        await _shiftRuleMappingRepository.SoftDeleteAsync(entity.Id);
        
        _logger.LogInformation($"班次{shiftId}删除规则{ruleId}成功");
    }

    /// <summary>
    /// 获取映射状态描述
    /// </summary>
    /// <param name="isEnabled">是否启用</param>
    /// <param name="effectiveStartTime">生效开始时间</param>
    /// <param name="effectiveEndTime">生效结束时间</param>
    /// <returns>状态描述</returns>
    private string GetMappingStatusDescription(bool isEnabled, DateTime? effectiveStartTime, DateTime? effectiveEndTime)
    {
        if (!isEnabled)
        {
            return "已禁用";
        }
        
        var now = DateTime.Now;
        
        if (effectiveStartTime.HasValue && now < effectiveStartTime.Value)
        {
            return "未生效";
        }
        
        if (effectiveEndTime.HasValue && now > effectiveEndTime.Value)
        {
            return "已过期";
        }
        
        return "正常";
    }
}