namespace SafeCampus.Application.Services.Business.DormitoryService;

public class DormitoryService:DbRepository<DormitoryInfo>,IDormitoryService
{
    public async Task<bool> Add(DormitoryInfoDto input)
    {
        var model = input.Adapt<DormitoryInfo>();
        await InsertAsync(model);
        return true;
    }

    public async Task<bool> Update(DormitoryInfoDto input)
    {
        if (!input.Id.HasValue)
        {
            throw Oops.Oh("请填写ID");
        }
        var model = await GetFirstAsync(p => p.Id == input.Id);
        if (model == null)
        {
            throw Oops.Oh("信息不存在");
        }
        var res = input.Adapt(model);
        await UpdateAsync(res);
        return true;
    }

    public async Task<DormitoryInfoDto> GetInfo(long id)
    {
        var query = await Context.Queryable<DormitoryInfo>()
            .Includes(x => x.PersonInfos,x=>x.PersonSetInfoItem)
            .Includes(x => x.PersonInfos,x=>x.PersonFacesList)
            .FirstAsync(x => x.Id == id);
        return query.Adapt<DormitoryInfoDto>();
    }

    public async Task<bool> Delete(List<long> id)
    {
        var personInfo = ChangeRepository<DbRepository<PersonInfo>>();//切换仓储
        var model = await GetListAsync(x => id.Contains(x.Id));
        if (!model.Any())
        {
            throw Oops.Oh("信息不存在");
        }

        foreach (var dormitoryInfo in model)
        {
            var isOK = await personInfo.IsAnyAsync(x => x.DormitoryId == dormitoryInfo.Id);
            if (isOK)
            {
                throw Oops.Oh($"{dormitoryInfo.Name}寝室下还有人员，请转移至其他寝室后在删除！");
            }
        }
        await DeleteAsync(model);
        return true;
    }

    public async Task<bool> SetAssignPerson(DormitorySetPersonInput input)
    {
        var model = await GetFirstAsync(x => x.Id == input.DormitoryId);
        if (model == null)
        {
            throw Oops.Oh("寝室不存在");
        }
        var personInfo = ChangeRepository<DbRepository<PersonInfo>>();//切换仓储
        await personInfo.Context.Updateable<PersonInfo>().SetColumns(x => x.DormitoryId == null)
            .Where(x => x.DormitoryId==input.DormitoryId).ExecuteCommandAsync();
        await personInfo.Context.Updateable<PersonInfo>().SetColumns(x => x.DormitoryId == input.DormitoryId)
            .Where(x => input.PersonIds.Contains(x.PersonId)).ExecuteCommandAsync();
        return true;
    }

    public async Task<SqlSugarPagedList<DormitoryInfoList>> GetPageList(DormitoryInfoSearch search)
    {
        var query = Context.Queryable<DormitoryInfo>()
            .Includes(x => x.PersonInfos)
            .WhereIF(search.Gender.HasValue, x => x.Gender == search.Gender)
            .WhereIF(!string.IsNullOrEmpty(search.Name), x => x.Name.Contains(search.Name))
            .WhereIF(search.BuildId.HasValue, x => x.BuildId == search.BuildId);

        var list = await query.OrderByDescending(x => x.CreateTime)
            .ToPagedListAsyncMapster<DormitoryInfo, DormitoryInfoList>(search.PageNum, search.PageSize);
        return list;
    }

    public async Task<SqlSugarPagedList<ReturnDormitoryList>> GetReturnPageList(ReturnDormitoryISearch search)
    {
        //var buildingInfo = ChangeRepository<DbRepository<BuildingInfo>>();//切换仓储
        //var build = await buildingInfo.GetFirstAsync(x => x.Id == search.BuildId);
        var query = Context.Queryable<DormitoryInfo>()
            .Includes(x=>x.BuildingInfoItem)
            .Includes(x1 => x1.PersonInfos,
                xx => xx.Attendances
                    .Where(x => x.Tick.Year == search.ReturnTime.Year && x.Tick.Month == search.ReturnTime.Month &&
                                //x.Tick.Day == search.ReturnTime.Day&&x.CameraId== build.InsCameraId).ToList())
                                x.Tick.Day == search.ReturnTime.Day).ToList())
            .WhereIF(search.Gender.HasValue, x => x.Gender == search.Gender)
            .WhereIF(!string.IsNullOrEmpty(search.Name), x => x.Name.Contains(search.Name))
            .WhereIF(search.BuildId.HasValue, x => x.BuildId == search.BuildId);

        var list = await query.OrderByDescending(x => x.CreateTime)
            .ToPagedListAsyncMapster<DormitoryInfo, ReturnDormitoryList>(search.PageNum, search.PageSize);
        return list;
    }
    public async Task<List<ReturnDormitoryList>> GetBiReturnPageList(ReturnDormitoryISearch search)
    {
        //var buildingInfo = ChangeRepository<DbRepository<BuildingInfo>>();//切换仓储
        //var build = await buildingInfo.GetFirstAsync(x => x.Id == search.BuildId);
        var query = Context.Queryable<DormitoryInfo>()
            .Includes(x => x.BuildingInfoItem)
            .Includes(x1 => x1.PersonInfos,
                xx => xx.Attendances
                    .Where(x => x.Tick.Year == search.ReturnTime.Year && x.Tick.Month == search.ReturnTime.Month &&
                                //x.Tick.Day == search.ReturnTime.Day&&x.CameraId== build.InsCameraId).ToList())
                                x.Tick.Day == search.ReturnTime.Day).ToList())
            //.WhereIF(search.Gender.HasValue, x => x.Gender == search.Gender)
            //.WhereIF(!string.IsNullOrEmpty(search.Name), x => x.Name.Contains(search.Name))
            .WhereIF(search.BuildId.HasValue, x => x.BuildId == search.BuildId);

        var list = await query.OrderByDescending(x => x.CreateTime)
            .ToListAsync();
            //.ToPagedListAsyncMapster<DormitoryInfo, ReturnDormitoryList>(search.PageNum, search.PageSize);
        return list.Adapt<List<ReturnDormitoryList>>();
    }

    public async Task<ReturnDormitoryDto> GetReturnInfo(long id, DateTime returnTime)
    {
        var query = await Context.Queryable<DormitoryInfo>()
            .Includes(x => x.PersonInfos, xx => xx.Attendances.Where(x =>
                    x.Tick.Year == returnTime.Year && x.Tick.Month == returnTime.Month &&
                    x.Tick.Day == returnTime.Day).ToList())
            .Includes(x=>x.PersonInfos,x=>x.PersonSetInfoItem)
            .Includes(x=>x.PersonInfos,x=>x.PersonFacesList)
            .FirstAsync(x => x.Id == id);
        return query.Adapt<ReturnDormitoryDto>();
    }
}