using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.SystemParameters.Commands;
using TakeoutSaaS.Application.App.SystemParameters.Dto;
using TakeoutSaaS.Domain.SystemParameters.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;

namespace TakeoutSaaS.Application.App.SystemParameters.Handlers;

/// <summary>
/// 更新系统参数命令处理器。
/// </summary>
public sealed class UpdateSystemParameterCommandHandler(
    ISystemParameterRepository repository,
    ILogger<UpdateSystemParameterCommandHandler> logger)
    : IRequestHandler<UpdateSystemParameterCommand, SystemParameterDto?>
{
    private readonly ISystemParameterRepository _repository = repository;
    private readonly ILogger<UpdateSystemParameterCommandHandler> _logger = logger;

    /// <inheritdoc />
    public async Task<SystemParameterDto?> Handle(UpdateSystemParameterCommand request, CancellationToken cancellationToken)
    {
        // 1. 读取已有参数
        var existing = await _repository.FindByIdAsync(request.ParameterId, cancellationToken);
        if (existing == null)
        {
            return null;
        }

        // 2. 唯一性校验
        var duplicate = await _repository.FindByKeyAsync(request.Key, cancellationToken);
        if (duplicate != null && duplicate.Id != existing.Id)
        {
            throw new BusinessException(ErrorCodes.Conflict, "系统参数键已存在");
        }

        // 3. 更新字段
        existing.Key = request.Key.Trim();
        existing.Value = request.Value.Trim();
        existing.Description = request.Description?.Trim();
        existing.SortOrder = request.SortOrder;
        existing.IsEnabled = request.IsEnabled;

        // 4. 持久化
        await _repository.UpdateAsync(existing, cancellationToken);
        await _repository.SaveChangesAsync(cancellationToken);
        _logger.LogInformation("更新系统参数 {Key}", existing.Key);

        return MapToDto(existing);
    }

    private static SystemParameterDto MapToDto(Domain.SystemParameters.Entities.SystemParameter parameter) => new()
    {
        Id = parameter.Id,
        TenantId = parameter.TenantId,
        Key = parameter.Key,
        Value = parameter.Value,
        Description = parameter.Description,
        SortOrder = parameter.SortOrder,
        IsEnabled = parameter.IsEnabled,
        CreatedAt = parameter.CreatedAt,
        UpdatedAt = parameter.UpdatedAt
    };
}
