using TakeoutSaaS.Application.Dictionary.Models;
using TakeoutSaaS.Domain.Dictionary.Entities;
using TakeoutSaaS.Domain.Dictionary.Enums;
using TakeoutSaaS.Domain.Dictionary.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;

namespace TakeoutSaaS.Application.Dictionary.Services;

/// <summary>
/// 字典标签覆盖服务。
/// </summary>
public sealed class DictionaryLabelOverrideService(
    IDictionaryLabelOverrideRepository overrideRepository,
    IDictionaryItemRepository itemRepository)
{
    /// <summary>
    /// 获取租户的所有标签覆盖。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="overrideType">可选的覆盖类型过滤。</param>
    /// <param name="cancellationToken">取消标记。</param>
    public async Task<IReadOnlyList<LabelOverrideDto>> GetOverridesAsync(
        long tenantId,
        OverrideType? overrideType = null,
        CancellationToken cancellationToken = default)
    {
        var overrides = await overrideRepository.ListByTenantAsync(tenantId, overrideType, cancellationToken);
        return overrides.Select(MapToDto).ToList();
    }

    /// <summary>
    /// 获取指定字典项的覆盖配置。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="dictionaryItemId">字典项 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    public async Task<LabelOverrideDto?> GetOverrideByItemIdAsync(
        long tenantId,
        long dictionaryItemId,
        CancellationToken cancellationToken = default)
    {
        var entity = await overrideRepository.GetByItemIdAsync(tenantId, dictionaryItemId, cancellationToken);
        return entity == null ? null : MapToDto(entity);
    }

    /// <summary>
    /// 创建或更新租户对系统字典的标签覆盖（租户定制）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="request">覆盖请求。</param>
    /// <param name="operatorId">操作人 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    public async Task<LabelOverrideDto> UpsertTenantOverrideAsync(
        long tenantId,
        UpsertLabelOverrideRequest request,
        long operatorId,
        CancellationToken cancellationToken = default)
    {
        // 1. 验证字典项存在且为系统字典
        var item = await itemRepository.GetByIdAsync(request.DictionaryItemId, cancellationToken);
        if (item == null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "字典项不存在");
        }

        if (item.TenantId != 0)
        {
            throw new BusinessException(ErrorCodes.ValidationFailed, "租户只能覆盖系统字典项");
        }

        // 2. 查找现有覆盖或创建新记录
        var existing = await overrideRepository.GetByItemIdAsync(tenantId, request.DictionaryItemId, cancellationToken);
        var now = DateTime.UtcNow;
        // 2.1 更新现有覆盖或创建新记录
        if (existing != null)
        {
            // 2.2 仅允许租户定制类型被租户修改，其他类型视为系统保留数据
            if (existing.OverrideType != OverrideType.TenantCustomization)
            {
                throw new BusinessException(ErrorCodes.Forbidden, "该覆盖记录不允许由租户修改");
            }

            existing.OverrideValue = DictionaryValueConverter.Serialize(request.OverrideValue);
            existing.Reason = request.Reason;
            existing.UpdatedAt = now;
            existing.UpdatedBy = operatorId;
            await overrideRepository.UpdateAsync(existing, cancellationToken);
        }
        else
        {
            existing = new DictionaryLabelOverride
            {
                TenantId = tenantId,
                DictionaryItemId = request.DictionaryItemId,
                OriginalValue = item.Value,
                OverrideValue = DictionaryValueConverter.Serialize(request.OverrideValue),
                OverrideType = OverrideType.TenantCustomization,
                Reason = request.Reason,
                CreatedAt = now,
                CreatedBy = operatorId
            };
            await overrideRepository.AddAsync(existing, cancellationToken);
        }

        await overrideRepository.SaveChangesAsync(cancellationToken);

        // 重新加载以获取完整信息
        existing.DictionaryItem = item;
        return MapToDto(existing);
    }

    /// <summary>
    /// 删除覆盖配置。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="dictionaryItemId">字典项 ID。</param>
    /// <param name="operatorId">操作人 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    public async Task<bool> DeleteOverrideAsync(
        long tenantId,
        long dictionaryItemId,
        long operatorId,
        CancellationToken cancellationToken = default)
    {
        var existing = await overrideRepository.GetByItemIdAsync(tenantId, dictionaryItemId, cancellationToken);
        if (existing == null)
        {
            return false;
        }

        // 1. (空行后) 仅允许删除租户定制类型，其他类型视为系统保留数据
        if (existing.OverrideType != OverrideType.TenantCustomization)
        {
            throw new BusinessException(ErrorCodes.Forbidden, "该覆盖记录不允许由租户删除");
        }

        existing.DeletedBy = operatorId;
        await overrideRepository.DeleteAsync(existing, cancellationToken);
        await overrideRepository.SaveChangesAsync(cancellationToken);
        return true;
    }

    /// <summary>
    /// 批量获取字典项的覆盖值映射。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="dictionaryItemIds">字典项 ID 列表。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>字典项 ID 到覆盖值的映射。</returns>
    public async Task<Dictionary<long, Dictionary<string, string>>> GetOverrideValuesMapAsync(
        long tenantId,
        IEnumerable<long> dictionaryItemIds,
        CancellationToken cancellationToken = default)
    {
        var overrides = await overrideRepository.GetByItemIdsAsync(tenantId, dictionaryItemIds, cancellationToken);
        return overrides.ToDictionary(
            x => x.DictionaryItemId,
            x => DictionaryValueConverter.Deserialize(x.OverrideValue));
    }

    private static LabelOverrideDto MapToDto(DictionaryLabelOverride entity)
    {
        return new LabelOverrideDto
        {
            Id = entity.Id,
            TenantId = entity.TenantId,
            DictionaryItemId = entity.DictionaryItemId,
            DictionaryItemKey = entity.DictionaryItem?.Key ?? string.Empty,
            OriginalValue = DictionaryValueConverter.Deserialize(entity.OriginalValue),
            OverrideValue = DictionaryValueConverter.Deserialize(entity.OverrideValue),
            OverrideType = entity.OverrideType,
            Reason = entity.Reason,
            CreatedAt = entity.CreatedAt,
            UpdatedAt = entity.UpdatedAt,
            CreatedBy = entity.CreatedBy,
            UpdatedBy = entity.UpdatedBy
        };
    }
}
