package com.yuchen.saas.park.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.manage.system.api.feign.IOrgUserClient;
import com.yuchen.saas.manage.system.api.request.OrgUserInfoRequest;
import com.yuchen.saas.manage.system.api.response.OrgUserInfoResponse;
import com.yuchen.saas.park.api.entity.park.*;
import com.yuchen.saas.park.api.enums.InspectStatusEnum;
import com.yuchen.saas.park.api.enums.TaskCompleteSituEnum;
import com.yuchen.saas.park.api.request.*;
import com.yuchen.saas.park.api.response.*;
import com.yuchen.saas.park.service.mapper.FireInspectPointMapper;
import com.yuchen.saas.park.service.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.Query;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.constant.NestConstant;
import org.nest.springwrap.core.tool.utils.Func;
import org.nest.springwrap.core.tool.utils.SpringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName FireInspectPointServiceImpl
 * @Description 消防巡查点服务实现类
 * @Author 肖祥
 * @Date 2022/10/19 13:42
 * @Version 1.0。0
 **/
@Service
public class FireInspectPointServiceImpl extends BaseServiceImpl<FireInspectPointMapper, FireInspectPointEntity>
        implements FireInspectPointService {

    @Resource
    private PmgBatParkInfoService pmgBatParkInfoService;

    @Resource
    private FireInspectFacilityRelService fireInspectFacilityRelService;

    @Resource
    private FireFacilityService fireFacilityService;

    @Resource
    private FireFacilityPartService fireFacilityPartService;

    @Resource
    private FirePointPlanRelService firePointPlanRelService;

    @Resource
    private FireInspectPlanService fireInspectPlanService;


    @Resource
    private FireInspectTaskService fireInspectTaskService;

    @Resource
    private PmgBatDeviceCategoryService pmgBatDeviceCategoryService;

    @Resource
    private FireTaskPartService fireTaskPartService;
    @Resource
    private IOrgUserClient orgUserClient;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> add(FireInspectAddRequest fireInspectAddRequest) {
        PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(fireInspectAddRequest.getAreaId());
        if (Func.isEmpty(deviceCategory)){
            throw new ServiceException("所选区域不存在！");
        }
//        PmgBatParkInfo pmgBatParkInfo = pmgBatParkInfoService.lambdaQuery().select(PmgBatParkInfo::getId).one();
        //新增巡查点
        FireInspectPointEntity pointEntity = new FireInspectPointEntity();
        BeanUtils.copyProperties(fireInspectAddRequest,pointEntity);
        pointEntity.setParkId(deviceCategory.getParkId());
        Boolean insert = save(pointEntity);

        List<FireInspectFacilityRelEntity> facilityRelEntityList = new ArrayList<>();
        //新增设施及部件
        fireInspectAddRequest.getFacilityAddRequestList().stream().forEach(inspectFacilityAddRequest->{
                FireInspectFacilityRelEntity facilityRelEntity = new FireInspectFacilityRelEntity();
                facilityRelEntity.setPartId(inspectFacilityAddRequest.getId());
                //根据部件id查询设施id
                FireFacilityPartEntity facilityPartEntity =  fireFacilityPartService.getById(inspectFacilityAddRequest.getId());
                facilityRelEntity.setFacilityId(facilityPartEntity.getFacilityId());
                facilityRelEntity.setInspectPointId(pointEntity.getId());
                facilityRelEntity.setParkId(deviceCategory.getParkId());
                facilityRelEntityList.add(facilityRelEntity);
                //update part remark
            LambdaUpdateWrapper<FireFacilityPartEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(FireFacilityPartEntity::getRemark,inspectFacilityAddRequest.getRemark());
            lambdaUpdateWrapper.eq(FireFacilityPartEntity::getId,inspectFacilityAddRequest.getId());
            fireFacilityPartService.update(new FireFacilityPartEntity(),lambdaUpdateWrapper);
        });
       boolean batchSave =  fireInspectFacilityRelService.saveBatch(facilityRelEntityList);
       if(!insert  || !batchSave){
           throw new ServiceException("新增巡查点失败");
       }
        return R.success("操作成功");
    }

    @Override
    public R<IPage<FireInspectListResponse>> listPage(FireInspectPointQueryRequest fireFacilityQueryRequest, Query query) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isEmpty(contextUser)){
            return R.data(Condition.getPage(query));
        }
        List<PmgBatParkInfo> pmgBatParkInfoList = pmgBatParkInfoService.getAllParkV1(null,contextUser.getIsAdmin(), contextUser.getDeptId(), contextUser.getTenantId(), contextUser.getOrgUserId());
        if (Func.isEmpty(pmgBatParkInfoList)){
            return R.data(Condition.getPage(query));
        }
        //分页查询
        LambdaQueryWrapper<FireInspectPointEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Func.isNotEmpty(fireFacilityQueryRequest.getName()),FireInspectPointEntity::getName,fireFacilityQueryRequest.getName());
        lambdaQueryWrapper.in(FireInspectPointEntity::getParkId,pmgBatParkInfoList.stream().map(PmgBatParkInfo::getId).collect(Collectors.toList()));
        //判断是否要查询子区域
        Set<Long> areaIds = new HashSet<>();
        if(Objects.equals(fireFacilityQueryRequest.getIncludeSubRegion(),1)){
            areaIds = pmgBatDeviceCategoryService.getParkingTreeById(fireFacilityQueryRequest.getAreaId()).getData();
            lambdaQueryWrapper.in(Func.isNotEmpty(areaIds),FireInspectPointEntity::getAreaId,areaIds);
        }
        if(areaIds.size() == 0 && Objects.nonNull(fireFacilityQueryRequest.getAreaId())){
            lambdaQueryWrapper.eq(Func.isNotEmpty(fireFacilityQueryRequest.getAreaId()),FireInspectPointEntity::getAreaId,fireFacilityQueryRequest.getAreaId());
        }
        lambdaQueryWrapper.orderByDesc(FireInspectPointEntity::getUpdateTime);
        IPage<FireInspectPointEntity> iPage = this.page(Condition.getPage(query),lambdaQueryWrapper);

        //组装返回response
        IPage<FireInspectListResponse> pageVo = new Page(iPage.getCurrent(), iPage.getSize(), iPage.getTotal());
        List<FireInspectListResponse> records = this.listVO(iPage.getRecords());
        pageVo.setRecords(records);
        return R.data(pageVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> delete(FireInspectDeleteRequest fireInspectDeleteRequest) {
        Integer count = firePointPlanRelService.lambdaQuery().eq(FirePointPlanRelEntity::getInspectPointId, fireInspectDeleteRequest.getId()).count();
        if (count>0){
            throw new ServiceException("此巡查点已绑定巡查计划，无法删除");
        }
        //删除巡查点
        LambdaUpdateWrapper<FireInspectPointEntity> fireInspectPointWrapper = new LambdaUpdateWrapper<>();
        fireInspectPointWrapper.set(FireInspectPointEntity::getIsDeleted,1);
        fireInspectPointWrapper.eq(FireInspectPointEntity::getId,fireInspectDeleteRequest.getId());
        Boolean update = update(new FireInspectPointEntity(),fireInspectPointWrapper);

        //删除巡查点关联的设施及任务
        LambdaQueryWrapper<FireInspectFacilityRelEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FireInspectFacilityRelEntity::getInspectPointId,fireInspectDeleteRequest.getId());
        boolean remove = fireInspectFacilityRelService.remove(lambdaQueryWrapper);
         if(!update || !remove){
             throw new ServiceException("删除巡查点失败");
         }
        return R.success("操作成功");
    }

    @Override
    public R<Boolean> update(FireInspectPointUpdateRequest updateRequest) {
        PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(updateRequest.getAreaId());
        if (Func.isEmpty(deviceCategory)){
            throw new ServiceException("所选区域不存在！");
        }
        //更新巡查点基本信息
        LambdaUpdateWrapper<FireInspectPointEntity> fireInspectPointWrapper = new LambdaUpdateWrapper<>();
        fireInspectPointWrapper.set(FireInspectPointEntity::getName,updateRequest.getName());
        fireInspectPointWrapper.set(FireInspectPointEntity::getInspectCard,updateRequest.getInspectCard());
        fireInspectPointWrapper.set(FireInspectPointEntity::getAreaId,updateRequest.getAreaId());
        fireInspectPointWrapper.set(FireInspectPointEntity::getParkId,deviceCategory.getParkId());
        fireInspectPointWrapper.set(FireInspectPointEntity::getDetailAddress,updateRequest.getDetailAddress());
        fireInspectPointWrapper.eq(FireInspectPointEntity::getId,updateRequest.getId());
        Boolean update = update(new FireInspectPointEntity(),fireInspectPointWrapper);

        //删除巡查点关联的设施及任务
        LambdaQueryWrapper<FireInspectFacilityRelEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FireInspectFacilityRelEntity::getInspectPointId,updateRequest.getId());
        boolean remove = fireInspectFacilityRelService.remove(lambdaQueryWrapper);
        //新增关联设施
        List<FireInspectFacilityRelEntity> relEntities = new ArrayList<>();
        //新增设施及部件
        updateRequest.getFacilityAddRequestList().stream().forEach(inspectFacilityAddRequest->{
                FireInspectFacilityRelEntity facilityRelEntity = new FireInspectFacilityRelEntity();
                facilityRelEntity.setPartId(inspectFacilityAddRequest.getId());
            //根据部件id查询设施id
            FireFacilityPartEntity facilityPartEntity =  fireFacilityPartService.getById(inspectFacilityAddRequest.getId());
            facilityRelEntity.setFacilityId(facilityPartEntity.getFacilityId());
                facilityRelEntity.setInspectPointId(updateRequest.getId());
                facilityRelEntity.setParkId(deviceCategory.getParkId());
                relEntities.add(facilityRelEntity);
            //update part remark
            LambdaUpdateWrapper<FireFacilityPartEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(FireFacilityPartEntity::getRemark,inspectFacilityAddRequest.getRemark());
            lambdaUpdateWrapper.eq(FireFacilityPartEntity::getId,inspectFacilityAddRequest.getId());
            fireFacilityPartService.update(new FireFacilityPartEntity(),lambdaUpdateWrapper);
        });
        boolean batchSave =  fireInspectFacilityRelService.saveBatch(relEntities);

        if(!update || !remove || !batchSave){
            throw new ServiceException("更新巡查点失败");
        }
        return R.success("操作成功");
    }

    @Override
    public R<FireInspectResponse> detail(Long id) {
        FireInspectResponse fireInspectResponse = new FireInspectResponse();
        //巡查点的信息
        FireInspectPointEntity fireInspectPoint = baseMapper.selectById(id);
        if(Objects.isNull(fireInspectPoint)){
            throw new ServiceException("detail not exist");
        }
        fireInspectResponse.setId(id);
        fireInspectResponse.setName(fireInspectPoint.getName());
        fireInspectResponse.setInspectCard(fireInspectPoint.getInspectCard());
        fireInspectResponse.setAreaId(fireInspectPoint.getAreaId());
        fireInspectResponse.setDetailAddress(fireInspectPoint.getDetailAddress());
        //巡查点关联的设施
        List<FireFacilityPartResponse> fireFacilityResponseList = new ArrayList<>();
       List<FireInspectFacilityRelEntity> relEntityList = fireInspectFacilityRelService.lambdaQuery()
                .eq(FireInspectFacilityRelEntity::getInspectPointId,id)
                .list();
        if(CollectionUtils.isNotEmpty(relEntityList)){
            relEntityList.stream().forEach(rel->{
                FireFacilityPartResponse fireFacilityResponse = new FireFacilityPartResponse();
                //根据设施id查询设施信息
                FireFacilityPartEntity partEntity = fireFacilityPartService.getById(rel.getPartId());
                 BeanUtils.copyProperties(partEntity,fireFacilityResponse);
                fireFacilityResponse.setParentId(partEntity.getFacilityId());
                fireFacilityResponse.setId(partEntity.getId());
                fireFacilityResponse.setName(partEntity.getName());
                fireFacilityResponseList.add(fireFacilityResponse);
            });
        }
        fireInspectResponse.setFireFacilityResponseList(fireFacilityResponseList);
        return R.data(fireInspectResponse);
    }

    @Override
    public R<IPage<FirePointPartResponse>> searchInspectPointPartPage(FirePointPartListRequest request, Query query) {
            //分页查询
            LambdaQueryWrapper<FireInspectFacilityRelEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FireInspectFacilityRelEntity::getInspectPointId,request.getPointId());
            IPage<FireInspectFacilityRelEntity> iPage = fireInspectFacilityRelService.page(Condition.getPage(query),lambdaQueryWrapper);

            //组装返回response
            IPage<FirePointPartResponse> pageVo = new Page(iPage.getCurrent(), iPage.getSize(), iPage.getTotal());
            List<FirePointPartResponse> records = this.listPartVO(iPage.getRecords(),request);
            pageVo.setRecords(records);
        return R.data(pageVo);
    }

    @Override
    public R<IPage<FireInspectPlanLogResponse>> searchInspectPointPlanPage(Long id, Query query) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isEmpty(contextUser)){
            return R.data(Condition.getPage(query));
        }
        List<PmgBatParkInfo> pmgBatParkInfoList = pmgBatParkInfoService.getAllParkV1(null,contextUser.getIsAdmin(), contextUser.getDeptId(), contextUser.getTenantId(), contextUser.getOrgUserId());
        if (Func.isEmpty(pmgBatParkInfoList)){
            return R.data(Condition.getPage(query));
        }
        //分页查询
        IPage<FireInspectPlanLogResponse> iPage = new Page<>(query.getCurrent(),query.getSize());
        IPage<FireInspectPlanLogResponse> pageVo = baseMapper.queryPage(iPage,id,pmgBatParkInfoList.stream().map(PmgBatParkInfo::getId).collect(Collectors.toList()));
        if(CollectionUtils.isNotEmpty(pageVo.getRecords())){
            for (FireInspectPlanLogResponse record : pageVo.getRecords()) {
                PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(record.getAreaId());
                if(deviceCategory != null){
                    Map<Long,PmgBatDeviceCategory> categoryMap = pmgBatDeviceCategoryService.list().stream().collect(Collectors.toMap(PmgBatDeviceCategory::getId, v -> v, (v1, v2) -> v2));
                    record.setAreaName(buildAreaName(deviceCategory.getParentId(),deviceCategory.getName(),categoryMap));
                }
                record.setCompleteSituName(TaskCompleteSituEnum.getDescByCode(record.getCompleteSitu()));
                OrgUserInfoRequest userInfoRequest = new OrgUserInfoRequest();
                userInfoRequest.setUserId(record.getInspectUser());
                List<OrgUserInfoResponse> userInfoResponseList = orgUserClient.findPatrolUser(userInfoRequest).getData();
                if (Func.isNotEmpty(userInfoResponseList)){
                    record.setInspectUserName(userInfoResponseList.get(0).getUserName());
                }
            }
        }
        return R.data(pageVo);
    }

    @Override
    public R<String> verifyPatrolPointInPlan(Long id) {
        LambdaQueryWrapper<FirePointPlanRelEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FirePointPlanRelEntity::getInspectPointId,id);
        List<FirePointPlanRelEntity> relList = firePointPlanRelService.list(lambdaQueryWrapper);
        List<String> planNameList = relList.stream().map(rel->{
            FireInspectPlanEntity planEntity = SpringUtil.getBean(FireInspectPlanService.class).getById(rel.getPlanId());
            return planEntity.getName();
        }).collect(Collectors.toList());
       String planListString = CollectionUtils.isEmpty(planNameList) ? "" : String.join(",",planNameList);
        return R.data(planListString);
    }

    @Override
    public R<List<FireInspectListResponse>> list(FireInspectPointQueryRequest fireFacilityQueryRequest) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isEmpty(contextUser)){
            return R.data(new ArrayList<>());
        }
        List<PmgBatParkInfo> pmgBatParkInfoList = pmgBatParkInfoService.getAllParkV1(null,contextUser.getIsAdmin(), contextUser.getDeptId(), contextUser.getTenantId(), contextUser.getOrgUserId());
        if (Func.isEmpty(pmgBatParkInfoList)){
            return R.data(new ArrayList<>());
        }
        LambdaQueryWrapper<FireInspectPointEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Func.isNotEmpty(fireFacilityQueryRequest.getName()),FireInspectPointEntity::getName,fireFacilityQueryRequest.getName());
        lambdaQueryWrapper.eq(Func.isNotEmpty(fireFacilityQueryRequest.getAreaId()),FireInspectPointEntity::getAreaId,fireFacilityQueryRequest.getAreaId());
        lambdaQueryWrapper.in(FireInspectPointEntity::getParkId,pmgBatParkInfoList.stream().map(PmgBatParkInfo::getId).collect(Collectors.toList()));
        List<FireInspectPointEntity> fireInspectPointEntityList = baseMapper.selectList(lambdaQueryWrapper);
        if(CollectionUtils.isEmpty(fireInspectPointEntityList)){
            return  R.data(Collections.EMPTY_LIST);
        }
        List<FireInspectListResponse> fireInspectListResponseList = fireInspectPointEntityList.stream().map(point->{
            FireInspectListResponse fireInspectListResponse = new FireInspectListResponse();
            fireInspectListResponse.setId(point.getId());
            fireInspectListResponse.setName(point.getName());
            return fireInspectListResponse;
        }).collect(Collectors.toList());
        return R.data(fireInspectListResponseList);
    }

    private  List<FireInspectListResponse> listVO(List<FireInspectPointEntity> list) {
        return (List)list.stream().map(entity->{
            FireInspectListResponse fireFacilityResponse = new FireInspectListResponse();
            BeanUtils.copyProperties(entity,fireFacilityResponse);
            PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(entity.getAreaId());
            if(deviceCategory != null){
                Map<Long,PmgBatDeviceCategory> categoryMap = pmgBatDeviceCategoryService.list().stream().collect(Collectors.toMap(PmgBatDeviceCategory::getId, v -> v, (v1, v2) -> v2));
                fireFacilityResponse.setAreaName(buildAreaName(deviceCategory.getParentId(),deviceCategory.getName(),categoryMap));
            }
            return fireFacilityResponse;
        }).collect(Collectors.toList());
    }
    private String buildAreaName(Long parentAreaId, String areaName,Map<Long,PmgBatDeviceCategory> categoryMap){
        if (!parentAreaId.equals(NestConstant.TOP_PARENT_ID)){
            PmgBatDeviceCategory deviceCategory = categoryMap.get(parentAreaId);
            if (Func.isNotEmpty(deviceCategory)){
                areaName=deviceCategory.getName()+"/"+areaName;
                buildAreaName(deviceCategory.getParentId(),areaName,categoryMap);
            }
        }
        return areaName;
    }
    private  List<FirePointPartResponse> listPartVO(List<FireInspectFacilityRelEntity> list,FirePointPartListRequest request) {
        return (List)list.stream().map(entity->{
            FirePointPartResponse fireInspectResponse = new FirePointPartResponse();
            FireFacilityPartEntity facilityPartEntity = fireFacilityPartService.getById(entity.getPartId());
            if(Objects.nonNull(facilityPartEntity)){
                if(Objects.nonNull(request.getTaskId())){
                    //根据任务id和部件id查询
                    LambdaQueryWrapper<FireTaskPartEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                    lambdaQueryWrapper.eq(FireTaskPartEntity::getTaskId,request.getTaskId());
                    lambdaQueryWrapper.eq(FireTaskPartEntity::getPartId,entity.getPartId());
                    FireTaskPartEntity fireTaskPartEntity = fireTaskPartService.getOne(lambdaQueryWrapper);
                    //异常描述
                    fireInspectResponse.setExceptionDesc(fireTaskPartEntity.getExceptionDesc());
                    //隐患详情
                    fireInspectResponse.setTroubleDetail(fireTaskPartEntity.getTroubleDetail());
                    fireInspectResponse.setStatusName(InspectStatusEnum.getDescByCode(fireTaskPartEntity.getPartInspectStatus()));
                }
                fireInspectResponse.setUpdateTime(entity.getUpdateTime());
                fireInspectResponse.setPartName(facilityPartEntity.getName());
                fireInspectResponse.setInspectStandard(facilityPartEntity.getInspectStandard());
            }
            return fireInspectResponse;
        }).collect(Collectors.toList());
    }
}
