using System.Text.Json;
using TakeoutSaaS.Application.Dictionary.Models;
using TakeoutSaaS.Domain.Dictionary.Entities;
using TakeoutSaaS.Domain.Dictionary.Enums;
using TakeoutSaaS.Domain.Dictionary.Repositories;

namespace TakeoutSaaS.Application.Dictionary.Services;

/// <summary>
/// 字典覆盖合并服务。
/// </summary>
public sealed class DictionaryMergeService(
    IDictionaryGroupRepository groupRepository,
    IDictionaryItemRepository itemRepository,
    ITenantDictionaryOverrideRepository overrideRepository)
{
    private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);

    /// <summary>
    /// 合并系统字典项与租户字典项。
    /// </summary>
    public async Task<IReadOnlyList<DictionaryItemDto>> MergeItemsAsync(
        long tenantId,
        long systemGroupId,
        CancellationToken cancellationToken = default)
    {
        var systemGroup = await groupRepository.GetByIdAsync(systemGroupId, cancellationToken);
        if (systemGroup == null || systemGroup.Scope != DictionaryScope.System || !systemGroup.IsEnabled)
        {
            return Array.Empty<DictionaryItemDto>();
        }

        var systemItems = await itemRepository.GetByGroupIdAsync(0, systemGroupId, cancellationToken);
        var activeSystem = systemItems.Where(item => item.IsEnabled).ToList();

        if (tenantId == 0)
        {
            return activeSystem.Select(DictionaryMapper.ToItemDto).ToList();
        }

        var overrideConfig = await overrideRepository.GetAsync(tenantId, systemGroupId, cancellationToken);
        if (overrideConfig == null || !overrideConfig.OverrideEnabled)
        {
            return activeSystem.Select(DictionaryMapper.ToItemDto).ToList();
        }

        var tenantGroup = await groupRepository.GetByCodeAsync(tenantId, systemGroup.Code, cancellationToken);
        var tenantItems = tenantGroup != null && tenantGroup.IsEnabled
            ? await itemRepository.GetByGroupIdAsync(tenantId, tenantGroup.Id, cancellationToken)
            : Array.Empty<DictionaryItem>();

        var activeTenant = tenantItems.Where(item => item.IsEnabled).ToList();
        var hiddenSet = new HashSet<long>(overrideConfig.HiddenSystemItemIds);
        var merged = activeSystem
            .Where(item => !hiddenSet.Contains(item.Id))
            .Concat(activeTenant)
            .Select(DictionaryMapper.ToItemDto)
            .ToList();

        var sortOrder = ParseSortOrder(overrideConfig.CustomSortOrder);
        return merged
            .OrderBy(item => sortOrder.TryGetValue(item.Id, out var custom) ? custom : item.SortOrder)
            .ThenBy(item => item.SortOrder)
            .ThenBy(item => item.Id)
            .ToList();
    }

    private static Dictionary<long, int> ParseSortOrder(string? json)
    {
        if (string.IsNullOrWhiteSpace(json))
        {
            return new Dictionary<long, int>();
        }

        try
        {
            return JsonSerializer.Deserialize<Dictionary<long, int>>(json, JsonOptions) ?? new Dictionary<long, int>();
        }
        catch (JsonException)
        {
            return new Dictionary<long, int>();
        }
    }
}
