using Hotline.SeedData;
using Hotline.Share.Dtos.Org;
using MapsterMapper;
using Microsoft.AspNetCore.Http;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Extensions;
using XF.Domain.Repository;

namespace Hotline.Settings;

public class SystemDomainService : ISystemDomainService, IScopeDependency
{
    private readonly ISystemOrganizeRepository _organizeRepository;
    private readonly IRepository<SystemDicData> _sysDicDataRepository;
    private readonly IMapper _mapper;

    public SystemDomainService(
        ISystemOrganizeRepository organizeRepository,
        IRepository<SystemDicData> sysDicDataRepository,
        IMapper mapper)
    {
        _organizeRepository = organizeRepository;
        _sysDicDataRepository = sysDicDataRepository;
        _mapper = mapper;
    }

    public async Task<IEnumerable<KeyValuePair<int, string>>> QueryOrgLevelOptionsAsync(
        CancellationToken cancellationToken)
    {
        var max = await _organizeRepository.Queryable()
            .MaxAsync(d => d.Level);

        var rsp = new List<KeyValuePair<int, string>>();
        for (int i = 1; i <= max; i++)
        {
            rsp.Add(new KeyValuePair<int, string>(i, $"{i.ToChinese()}级部门"));
        }

        return rsp;
    }

    public async Task<IEnumerable<KeyValuePair<string, string>>> QueryOrgLevelStringOptionsAsync(
        CancellationToken cancellationToken)
    {
        var rsp = await QueryOrgLevelOptionsAsync(cancellationToken);
        return rsp.Select(d => new KeyValuePair<string, string>(d.Key.ToString(), d.Value));
    }

    public async Task<IReadOnlyList<SystemDicData>> GetSysDicDataByCodeAsync(string code,
        CancellationToken cancellationToken = default)
    {
        return await _sysDicDataRepository.Queryable().Where(x => x.DicTypeCode == code)
            .ToTreeAsync(x => x.Children, x => x.ParentId, "");
    }

    /// <summary>
    /// 生成新的部门编码
    /// </summary>
    /// <param name="parentId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> GenerateNewOrgCodeAsync(string? parentId, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(parentId))
        {
            //一级部门
            var maxCode = await _organizeRepository.Queryable()
                .Where(d => d.Level == 1)
                .MaxAsync(d => d.Id, cancellationToken);

            if (!int.TryParse(maxCode.GetLastOrgId(), out var max))
                throw new UserFriendlyException("无效部门编码");
            return (max + 1).ToString("000");
        }
        else
        {
            var parentOrg = await _organizeRepository.GetAsync(parentId, cancellationToken);
            if (parentOrg == null)
                throw new UserFriendlyException("无效上级部门编码");

            var maxCode = await _organizeRepository.Queryable()
                .Where(d => d.ParentId == parentId)
                .MaxAsync(d => d.Id, cancellationToken);

            if (string.IsNullOrEmpty(maxCode))
                return $"{parentOrg.Id}001";

            if (!int.TryParse(maxCode.GetLastOrgId(), out var max))
                throw new UserFriendlyException("无效部门编码");

            return $"{parentOrg.Id}{(max + 1):000}";
        }
    }

    /// <summary>
    /// 部门名称是否重复
    /// </summary>
    /// <param name="orgname"></param>
    /// <returns></returns>
    public async Task<int> IsNameRepeat(string orgname, CancellationToken cancellationToken)
    {
        return await _organizeRepository.CountAsync(x => x.Name == orgname, cancellationToken);
    }

    /// <summary>
    /// 部门简称是否重复
    /// </summary>
    /// <param name="orgShrotName"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<int> IsShrotNameRepeat(string orgShrotName, CancellationToken cancellationToken)
    {
        return await _organizeRepository.CountAsync(x => x.ShortName == orgShrotName, cancellationToken);
    }

    /// <summary>
    /// 新增部门
    /// </summary>
    public async Task AddOrgAsync(AddOrgDto dto, CancellationToken cancellationToken)
    {
        var org = _mapper.Map<SystemOrganize>(dto);

        if (string.IsNullOrEmpty(dto.ParentId))
        {
            //一级部门
            var maxCode = await _organizeRepository.Queryable(includeDeleted:true)
                .Where(d => d.Level == 1)
                .MaxAsync(d => d.Id, cancellationToken);

            if (string.IsNullOrEmpty(maxCode))
            {
                org.Id = "001";
            }
            else
            {
                if (!int.TryParse(maxCode.GetLastOrgId(), out var max))
                    throw new UserFriendlyException("无效部门编码");

                org.Id = $"{OrgSeedData.CenterId}{(max + 1):000}";
            }
            org.IsCenter = false;
            org.Level = 1;
        }
        else
        {
            if (dto.ParentId.IsCenter())
                throw new UserFriendlyException("暂不支持中心创建下级部门");

            var parentOrg = await _organizeRepository.GetAsync(dto.ParentId, cancellationToken);
            if (parentOrg == null)
                throw new UserFriendlyException("无效上级部门编码");

            var maxCode = await _organizeRepository.Queryable(includeDeleted:true)
                .Where(d => d.ParentId == dto.ParentId)
                .MaxAsync(d => d.Id, cancellationToken);

            if (string.IsNullOrEmpty(maxCode))
            {
                org.Id = $"{parentOrg.Id}001";
            }
            else
            {
                if (!int.TryParse(maxCode.GetLastOrgId(), out var max))
                    throw new UserFriendlyException("无效部门编码");

                org.Id = $"{parentOrg.Id}{(max + 1):000}";
            }
            org.IsCenter = parentOrg.IsCenter;
            org.Level = parentOrg.Level + 1;
        }

        await _organizeRepository.AddAsync(org, cancellationToken);
    }
}