using Furion.DatabaseAccessor.Extensions;
using YBEE.EQM.Core;

namespace YBEE.EQM.Application;

/// <summary>
/// 被监测机构管理服务
/// </summary>
public class ExamOrgService : IExamOrgService, ITransient
{
    private readonly IRepository<ExamOrg> _rep;
    public ExamOrgService(IRepository<ExamOrg> rep)
    {
        _rep = rep;
    }

    /// <summary>
    /// 添加机构
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task AddList(AddExamOrgListInput input)
    {
        var existsOrgIdList = await _rep.Where(t => t.ExamPlanId == input.ExamPlanId).Select(t => t.SysOrgId).ToListAsync();
        var addOrgIdList = from t in input.SysOrgIdList where !(from rid in existsOrgIdList select rid).Contains(t) select t;
        var roles = addOrgIdList.Select(u => new ExamOrg
        {
            ExamPlanId = input.ExamPlanId,
            SysOrgId = u,
        }).ToList();
        await _rep.InsertAsync(roles);
    }
    /// <summary>
    /// 移出机构
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task Remove(DelExamOrgInput input)
    {
        var roleUsers = await _rep.Where(t => input.IdList.Contains(t.Id)).ToListAsync();
        await _rep.DeleteAsync(roleUsers);
    }
    /// <summary>
    /// 切换机构是否参与区统一监测
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task SwitchRequiredSample(SwitchExamOrgRequiredSampleInput input)
    {
        var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
        item.IsRequiredExam = input.IsRequiredExam;
        await item.UpdateIncludeAsync(new[] { nameof(item.IsRequiredExam) });
    }
    /// <summary>
    /// 根据监测计划ID获取监测机构列表
    /// </summary>
    /// <param name="examPlanId"></param>
    /// <returns></returns>
    public async Task<List<ExamOrgOutput>> GetListByExamPlanId(int examPlanId)
    {
        var items = await _rep.DetachedEntities.Where(t => t.ExamPlanId == examPlanId).ProjectToType<ExamOrgOutput>().ToListAsync();

        var odrs = await _rep.Change<ExamOrgDataReport>().Where(t => t.ExamOrg.ExamPlanId == examPlanId).ToListAsync();
        foreach (var item in items)
        {
            item.DataReports = odrs.Where(t => t.ExamOrgId == item.Id).ToDictionary(t => (short)t.Type, u => u.Status);
        }
        return items;
    }
    /// <summary>
    /// 分页查询监测机构列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<PageResult<ExamOrgOutput>> QueryPageList(ExamOrgPageInput input)
    {
        var orgName = !string.IsNullOrEmpty(input.OrgName?.Trim());

        var ret = await _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId)
                                             .Where((orgName, u => EF.Functions.Like(u.SysOrg.FullName, $"%{input.OrgName.Trim()}%")))
                                             .ProjectToType<ExamOrgOutput>()
                                             .ToADPagedListAsync(input.PageIndex, input.PageSize);

        var odrs = await _rep.Change<ExamOrgDataReport>().Where(t => t.ExamOrg.ExamPlanId == input.ExamPlanId).ProjectToType<ExamOrgDataReportOutput>().ToListAsync();
        foreach (var item in ret.Items)
        {
            item.DataReportList = odrs.Where(t => t.ExamOrgId == item.Id).ToList();
            item.DataReports = item.DataReportList.ToDictionary(t => (short)t.Type, u => u.Status);
        }

        return ret;
    }
    /// <summary>
    /// 分页查询未加入的机构
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<PageResult<SysOrgLiteOutput>> QueryNotInSysOrgPageList(ExamOrgNotInPageInput input)
    {
        var code = !string.IsNullOrEmpty(input.Code?.Trim());
        var name = !string.IsNullOrEmpty(input.Name?.Trim());

        var examPlan = await _rep.Change<ExamPlan>().DetachedEntities.FirstOrDefaultAsync(t => t.Id == input.ExamPlanId);
        var inOrgIds = await _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId).Select(t => t.SysOrgId).ToListAsync();
        var ret = await _rep.Change<SysOrg>().DetachedEntities
                                                   .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                                   .Where((name, u => EF.Functions.Like(u.FullName, $"%{input.Name.Trim()}%")))
                                                   .Where(input.UrbanRuralType.HasValue, t => t.UrbanRuralType == input.UrbanRuralType)
                                                   .Where(input.Status.HasValue, t => t.Status == input.Status)
                                                   .Where(t => t.OrgType == OrgType.SCHOOL && t.EducationStage == examPlan.EducationStage && t.UrbanRuralType != UrbanRuralType.NONE && !inOrgIds.Contains(t.Id))
                                                   .ProjectToType<SysOrgLiteOutput>()
                                                   .ToADPagedListAsync(input.PageIndex, input.PageSize);
        return ret;
    }
    /// <summary>
    /// 分页查询机构监测计划列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<PageResult<ExamPlanOutput>> QueryExamPlanPageList(ExamPlanPageInput input)
    {
        var name = !string.IsNullOrEmpty(input.Name?.Trim());
        var searchBeginTime = !string.IsNullOrEmpty(input.SearchBeginTime?.Trim());
        var searchEndTime = !string.IsNullOrEmpty(input.SearchEndTime?.Trim());
        var ret = await _rep.DetachedEntities.Where(t => t.SysOrgId == CurrentSysUserInfo.SysOrgId && (t.ExamPlan.Status == ExamStatus.ACTIVE || t.ExamPlan.Status == ExamStatus.STOPPED) && t.ExamPlan.IsDeleted == false)
                                             .Where((name, u => EF.Functions.Like(u.ExamPlan.Name, $"%{input.Name.Trim()}%") || EF.Functions.Like(u.ExamPlan.FullName, $"%{input.Name.Trim()}%") || EF.Functions.Like(u.ExamPlan.ShortName, $"%{input.Name.Trim()}%")))
                                             .Where(input.EducationStage.HasValue, t => t.ExamPlan.EducationStage == input.EducationStage)
                                             //.Where(input.ExamPeriodType.HasValue, t => t.ExamPlan.ExamPeriodType == input.ExamPeriodType)
                                             //.Where(input.ExamType.HasValue, t => t.ExamPlan.ExamType == input.ExamType)
                                             .Where(input.SemesterId.HasValue, t => t.ExamPlan.SemesterId == input.SemesterId)
                                             .Where(t => (t.ExamPlan.Status == ExamStatus.ACTIVE || t.ExamPlan.Status == ExamStatus.STOPPED) && (!input.Status.HasValue || input.Status.HasValue && t.ExamPlan.Status == input.Status))
                                             .Where((searchBeginTime, u => u.ExamPlan.CreateTime >= DateTime.Parse(input.SearchBeginTime)))
                                             .Where((searchEndTime, u => u.ExamPlan.CreateTime <= DateTime.Parse(input.SearchEndTime)))
                                             .OrderByDescending(t => t.ExamPlanId)
                                             .Select(t => t.ExamPlan).ProjectToType<ExamPlanOutput>().ToADPagedListAsync(input.PageIndex, input.PageSize);

        return ret;
    }
}
