using System.Text.Json;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Domain.Identity.Entities;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 菜单映射辅助。
/// </summary>
internal static class MenuMapper
{
    /// <summary>
    /// 将菜单实体映射为 DTO。
    /// </summary>
    /// <param name="entity">菜单实体。</param>
    /// <returns>菜单定义 DTO。</returns>
    public static MenuDefinitionDto ToDto(MenuDefinition entity)
    {
        // 1. 解析权限字段
        var requiredPermissions = SplitCodes(entity.RequiredPermissions);
        var metaPermissions = SplitCodes(entity.MetaPermissions);
        var metaRoles = SplitCodes(entity.MetaRoles);

        // 2. 解析按钮权限
        var authList = string.IsNullOrWhiteSpace(entity.AuthListJson)
            ? []
            : JsonSerializer.Deserialize<List<MenuAuthItemDto>>(entity.AuthListJson) ?? [];

        // 3. 输出 DTO
        return new MenuDefinitionDto
        {
            Id = entity.Id,
            ParentId = entity.ParentId,
            Name = entity.Name,
            Path = entity.Path,
            Component = entity.Component,
            Title = entity.Title,
            Icon = entity.Icon,
            IsIframe = entity.IsIframe,
            Link = entity.Link,
            KeepAlive = entity.KeepAlive,
            SortOrder = entity.SortOrder,
            RequiredPermissions = requiredPermissions,
            MetaPermissions = metaPermissions,
            MetaRoles = metaRoles,
            AuthList = authList
        };
    }

    /// <summary>
    /// 将 DTO 字段填充到实体。
    /// </summary>
    /// <param name="entity">菜单实体。</param>
    /// <param name="dto">菜单 DTO。</param>
    public static void FillEntity(MenuDefinition entity, MenuDefinitionDto dto)
    {
        // 1. 赋值基础字段
        entity.ParentId = dto.ParentId;
        entity.Name = dto.Name;
        entity.Path = dto.Path;
        entity.Component = dto.Component;
        entity.Title = dto.Title;
        entity.Icon = dto.Icon;
        entity.IsIframe = dto.IsIframe;
        entity.Link = dto.Link;
        entity.KeepAlive = dto.KeepAlive;
        entity.SortOrder = dto.SortOrder;

        // 2. 权限与按钮
        entity.RequiredPermissions = JoinCodes(dto.RequiredPermissions);
        entity.MetaPermissions = JoinCodes(dto.MetaPermissions);
        entity.MetaRoles = JoinCodes(dto.MetaRoles);
        entity.AuthListJson = dto.AuthList.Count == 0
            ? null
            : JsonSerializer.Serialize(dto.AuthList);
    }

    /// <summary>
    /// 构建或更新菜单实体并返回 DTO。
    /// </summary>
    /// <param name="existing">已存在的菜单实体。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="name">菜单名称。</param>
    /// <param name="payload">菜单 DTO 载荷。</param>
    /// <returns>菜单定义 DTO。</returns>
    public static MenuDefinitionDto FromCommand(MenuDefinition? existing, long tenantId, string name, MenuDefinitionDto payload)
    {
        // 1. 构造实体
        var entity = existing ?? new MenuDefinition
        {
            TenantId = tenantId,
            CreatedAt = DateTime.UtcNow
        };

        // // 填充字段
        FillEntity(entity, payload);

        // 2. 返回 DTO 映射
        return ToDto(entity);
    }

    /// <summary>
    /// 将权限/角色集合合并为存储字符串。
    /// </summary>
    /// <param name="codes">编码集合。</param>
    /// <returns>逗号分隔字符串。</returns>
    public static string JoinCodes(IEnumerable<string> codes)
    {
        return string.Join(',', codes.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct(StringComparer.OrdinalIgnoreCase));
    }

    /// <summary>
    /// 将逗号分隔编码拆分为集合。
    /// </summary>
    /// <param name="codes">编码字符串。</param>
    /// <returns>编码数组。</returns>
    public static string[] SplitCodes(string? codes)
    {
        if (string.IsNullOrWhiteSpace(codes))
        {
            return Array.Empty<string>();
        }

        return codes
            .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToArray();
    }
}
