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.core.toolkit.CollectionUtils;
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.manage.user.api.feign.IUserClient;
import com.yuchen.saas.manage.user.api.feign.UserFeignServer;
import com.yuchen.saas.park.api.entity.park.*;
import com.yuchen.saas.park.api.enums.PlanCycleEnum;
import com.yuchen.saas.park.api.enums.PlanStatusEnum;
import com.yuchen.saas.park.api.enums.TaskCompleteSituEnum;
import com.yuchen.saas.park.api.enums.TaskStatusEnum;
import com.yuchen.saas.park.api.request.*;
import com.yuchen.saas.park.api.response.FireInspectPlanListResponse;
import com.yuchen.saas.park.api.response.FireInspectPlanPointResponse;
import com.yuchen.saas.park.api.response.FireInspectPlanResponse;
import com.yuchen.saas.park.service.mapper.FireInspectPlanMapper;
import com.yuchen.saas.park.service.service.*;
import com.yuchen.saas.parking.api.util.DateUtils;
import org.apache.commons.lang.StringUtils;
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.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @ClassName FireInspectPlanServiceImpl
 * @Description 消防巡查计划服务实现类
 * @Author 肖祥
 * @Date 2022/10/20 10:52
 * @Version 1.0。0
 **/
@Service
public class FireInspectPlanServiceImpl extends BaseServiceImpl<FireInspectPlanMapper, FireInspectPlanEntity>
        implements FireInspectPlanService {

    @Resource
    private PmgBatParkInfoService pmgBatParkInfoService;

    @Resource
    private FirePointPlanRelService firePointPlanRelService;

    @Resource
    private PmgBatDeviceCategoryService pmgBatDeviceCategoryService;
    @Resource
    @Lazy
    private FireInspectPointService fireInspectPointService;

   /* @Resource
    private IUserService userService;*/
   @Resource
   private UserFeignServer userFeignServer;
    @Resource
    private IOrgUserClient orgUserClient;
    @Resource
    private IUserClient userClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Long> add(FireInspectPlanAddRequest planAddRequest) {

        PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(planAddRequest.getAreaId());
        if (Func.isEmpty(deviceCategory)){
            throw new ServiceException("所选区域不存在");
        }
        //新增计划主表
        FireInspectPlanEntity planEntity = new FireInspectPlanEntity();
        BeanUtils.copyProperties(planAddRequest,planEntity);
        planEntity.setPlanStartDate(DateUtils.parseDate(DateUtils.DATE_YYYY_MM_DD_PATTERN,planAddRequest.getPlanStartDate()));
        planEntity.setPlanEndDate(DateUtils.parseDate(DateUtils.DATE_YYYY_MM_DD_PATTERN,planAddRequest.getPlanEndDate()));
        if(Objects.equals(planAddRequest.getInspectCycle(), PlanCycleEnum.DAY_MORE.getCode())){
            planEntity.setStartTime(DateUtils.parseSqlTime(planAddRequest.getStartTime()));
            planEntity.setEndTime(DateUtils.parseSqlTime(planAddRequest.getEndTime()));
            planEntity.setPlanInterval(planAddRequest.getPlanInterval());
        }
        planEntity.setPlanStatus(PlanStatusEnum.NO_START.getCode());
        planEntity.setParkId(deviceCategory.getParkId());
        boolean insert = this.save(planEntity);

        //关联计划巡查点
        List<FirePointPlanRelEntity> relAddEntityList = new ArrayList<>();
        List<FireInspectPointEntity> inspectPointEntityList = fireInspectPointService.list();
        Map<Long, FireInspectPointEntity> pointMap = inspectPointEntityList.stream().collect(Collectors.toMap(FireInspectPointEntity::getId, v -> v, (v1, v2) -> v2));
        for (Long pointId : planAddRequest.getInspectPointIds()) {
            FireInspectPointEntity fireInspectPointEntity = pointMap.get(pointId);
            if (Func.isEmpty(fireInspectPointEntity)){
                throw new ServiceException(fireInspectPointEntity.getName()+"巡查点已被删除！");
            }
            FirePointPlanRelEntity facilityRelEntity = new FirePointPlanRelEntity();
                    //设置巡查点计划id
                    facilityRelEntity.setInspectPointId(pointId);
                    facilityRelEntity.setPlanId(planEntity.getId());
                    facilityRelEntity.setParkId(deviceCategory.getParkId());
                    relAddEntityList.add(facilityRelEntity);
        }
        //更新关联表
        boolean batchUpdate =  firePointPlanRelService.saveBatch(relAddEntityList);
        if(!insert || !batchUpdate){
            throw new ServiceException("新增巡查计划失败");
        }
        return R.data(planEntity.getId());
    }

    @Override
    public R<IPage<FireInspectPlanListResponse>> list(FireInspectPlanQueryRequest planQueryRequest, 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<FireInspectPlanEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Func.isNotBlank(planQueryRequest.getName()),FireInspectPlanEntity::getName,planQueryRequest.getName());
        lambdaQueryWrapper.in(FireInspectPlanEntity::getParkId,pmgBatParkInfoList.stream().map(PmgBatParkInfo::getId).collect(Collectors.toList()));
        //判断是否要查询子区域
        Set<Long> areaIds = new HashSet<>();
        if(Objects.equals(planQueryRequest.getIncludeSubRegion(),1)){
            areaIds = pmgBatDeviceCategoryService.getParkingTreeById(planQueryRequest.getAreaId()).getData();
            lambdaQueryWrapper.in(Func.isNotEmpty(areaIds),FireInspectPlanEntity::getAreaId,areaIds);
        }
        if(areaIds.size() == 0 && Objects.nonNull(planQueryRequest.getAreaId())){
            lambdaQueryWrapper.eq(Func.isNotEmpty(planQueryRequest.getAreaId()),FireInspectPlanEntity::getAreaId,planQueryRequest.getAreaId());
        }
        if(StringUtils.isNotBlank(planQueryRequest.getInspectUserName())){
            OrgUserInfoRequest userInfoRequest = new OrgUserInfoRequest();
            userInfoRequest.setUserName(planQueryRequest.getInspectUserName());
            List<OrgUserInfoResponse> userInfoResponseList = orgUserClient.findPatrolUser(userInfoRequest).getData();
            if(CollectionUtils.isNotEmpty(userInfoResponseList)){
                List<Long> userIds = userInfoResponseList.stream().map(user->user.getUserId()).collect(Collectors.toList());
                lambdaQueryWrapper.in(FireInspectPlanEntity::getInspectUser,userIds);
            }else {
                lambdaQueryWrapper.eq(Func.isNotEmpty(planQueryRequest.getInspectUserName()),FireInspectPlanEntity::getInspectUser,0L);
            }
        }
        lambdaQueryWrapper.eq(Objects.nonNull(planQueryRequest.getPlanStatus()),FireInspectPlanEntity::getPlanStatus,planQueryRequest.getPlanStatus());
        lambdaQueryWrapper.eq(Objects.nonNull(planQueryRequest.getInspectCycle()),FireInspectPlanEntity::getInspectCycle,planQueryRequest.getInspectCycle());
        lambdaQueryWrapper.orderByDesc(FireInspectPlanEntity::getUpdateTime);
        IPage<FireInspectPlanEntity> iPage = this.page(Condition.getPage(query),lambdaQueryWrapper);

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> over(FireInspectPlanOverRequest fireInspectPlanOverRequest) {
        //更新主表状态
        LambdaUpdateWrapper<FireInspectPlanEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getPlanStatus,3)
                .eq(FireInspectPlanEntity::getId,fireInspectPlanOverRequest.getId());
        int updatePlan = baseMapper.update(new FireInspectPlanEntity(),lambdaUpdateWrapper);

        //更新任务表的状态
        LambdaUpdateWrapper<FireInspectTaskEntity> lambdaTaskWrapper= new LambdaUpdateWrapper<>();
        lambdaTaskWrapper.set(FireInspectTaskEntity::getTaskStatus, TaskStatusEnum.OVER.getCode());
        lambdaTaskWrapper.set(FireInspectTaskEntity::getTaskCompletionSituation, TaskCompleteSituEnum.EXCEPTION_STOP.getCode());
        lambdaTaskWrapper.eq(FireInspectTaskEntity::getInspectPlanId,fireInspectPlanOverRequest.getId());
        boolean updateTask = SpringUtil.getBean(FireInspectTaskService.class).update(new FireInspectTaskEntity(),lambdaTaskWrapper);

        if(updatePlan < 1 || !updateTask){
            throw new ServiceException("计划结束失败");
        }

        return R.success("操作成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> delete(FireInspectPlanDeleteRequest planDeleteRequest) {
        //更新主表
        LambdaUpdateWrapper<FireInspectPlanEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getIsDeleted,1)
                .eq(FireInspectPlanEntity::getId,planDeleteRequest.getId());
        Boolean updatePlan = update(new FireInspectPlanEntity(),lambdaUpdateWrapper);

        //删除关联表的数据,物理删除
       List<FirePointPlanRelEntity>  facilityRelEntities = firePointPlanRelService.lambdaQuery()
               .eq(FirePointPlanRelEntity::getPlanId,planDeleteRequest.getId())
               .list();
        List<Long> relIds = new ArrayList<>();
        for (FirePointPlanRelEntity fireInspectTaskEntity : facilityRelEntities) {
            relIds.add(fireInspectTaskEntity.getId());
        }
       boolean deleteRel =  firePointPlanRelService.removeByIds(relIds);

        //删除任务表的数据,逻辑删除
        LambdaQueryWrapper<FireInspectTaskEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FireInspectTaskEntity::getInspectPlanId,planDeleteRequest.getId());
        List<FireInspectTaskEntity> fireInspectTaskEntityList = SpringUtil.getBean(FireInspectTaskService.class).list(lambdaQueryWrapper);
        List<Long> ids = new ArrayList<>();
        for (FireInspectTaskEntity fireInspectTaskEntity : fireInspectTaskEntityList) {
            ids.add(fireInspectTaskEntity.getId());
        }
        boolean deleteTask = SpringUtil.getBean(FireInspectTaskService.class).deleteLogic(ids);

        if(!updatePlan || !deleteTask || !deleteRel){
            throw new ServiceException("计划结束失败");
        }
        return R.success("操作成功");
    }

    @Override
    public R<Boolean> update(FireInspectPlanUpdateRequest updateRequest) {
        PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(updateRequest.getAreaId());
        if (Func.isEmpty(deviceCategory)){
            throw new ServiceException("所选区域不存在");
        }
        //更新主表
        LambdaUpdateWrapper<FireInspectPlanEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getPlanStartDate,DateUtils.parseDate(DateUtils.DATE_YYYY_MM_DD_PATTERN,updateRequest.getPlanStartDate()));
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getPlanEndDate,DateUtils.parseDate(DateUtils.DATE_YYYY_MM_DD_PATTERN,updateRequest.getPlanEndDate()));
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getName,updateRequest.getName());
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getAreaId,updateRequest.getAreaId());
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getParkId,deviceCategory.getParkId());
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getInspectUser,updateRequest.getInspectUser());
        lambdaUpdateWrapper.set(FireInspectPlanEntity::getInspectCycle,updateRequest.getInspectCycle());
        lambdaUpdateWrapper.eq(FireInspectPlanEntity::getId,updateRequest.getId());
        if(Objects.equals(updateRequest.getInspectCycle(),PlanCycleEnum.DAY_MORE.getCode())){
            lambdaUpdateWrapper.set(FireInspectPlanEntity::getStartTime,DateUtils.parseSqlTime(updateRequest.getStartTime()));
            lambdaUpdateWrapper.set(FireInspectPlanEntity::getEndTime,DateUtils.parseSqlTime(updateRequest.getEndTime()));
            lambdaUpdateWrapper.set(FireInspectPlanEntity::getPlanInterval,updateRequest.getPlanInterval());
        }
        Boolean update = update(new FireInspectPlanEntity(),lambdaUpdateWrapper);

        //先把原来计划关联的删除掉
        LambdaQueryWrapper<FirePointPlanRelEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FirePointPlanRelEntity::getPlanId,updateRequest.getId());
        List<FirePointPlanRelEntity>  facilityRelEntityList = firePointPlanRelService.list(lambdaQueryWrapper);
        List<Long> ids = new ArrayList<>();
        for (FirePointPlanRelEntity facilityRelEntity : facilityRelEntityList) {
            ids.add(facilityRelEntity.getId());
        }
        if(CollectionUtils.isNotEmpty(ids)){
            firePointPlanRelService.removeByIds(ids);
        }

        //关联计划巡查点
        List<FirePointPlanRelEntity> relAddEntityList = new ArrayList<>();
        for (Long pointId : updateRequest.getInspectPointIds()) {
            FirePointPlanRelEntity facilityRelEntity = new FirePointPlanRelEntity();
            //设置巡查点计划id
            facilityRelEntity.setInspectPointId(pointId);
            facilityRelEntity.setPlanId(updateRequest.getId());
            facilityRelEntity.setParkId(deviceCategory.getParkId());
            relAddEntityList.add(facilityRelEntity);
        }

        //更新关联表
        boolean batchUpdate =  firePointPlanRelService.saveBatch(relAddEntityList);
        if(!update || !batchUpdate){
            throw new ServiceException("巡查计划更新失败");
        }
        return R.success("操作成功");
    }

    @Override
    public R<FireInspectPlanResponse> detail(Long id) {
        FireInspectPlanResponse response = new FireInspectPlanResponse();
        //查询主表的信息
         FireInspectPlanEntity fireInspectPlanEntity =   baseMapper.selectById(id);
         BeanUtils.copyProperties(fireInspectPlanEntity,response);
        PmgBatDeviceCategory deviceCategory = pmgBatDeviceCategoryService.getById(fireInspectPlanEntity.getAreaId());
        response.setAreaName(deviceCategory.getName());
        response.setInspectCycleName(PlanCycleEnum.getDescByCode(fireInspectPlanEntity.getInspectCycle()));
        OrgUserInfoRequest userInfoRequest = new OrgUserInfoRequest();
        userInfoRequest.setUserId(fireInspectPlanEntity.getInspectUser());
        List<OrgUserInfoResponse> userInfoResponseList = orgUserClient.findPatrolUser(userInfoRequest).getData();
        if (Func.isNotEmpty(userInfoResponseList)){
            response.setInspectUserName(userInfoResponseList.get(0).getUserName());
        }
        //根据计划id查询关联表巡查点
        List<Long> relEntityList = firePointPlanRelService.lambdaQuery()
                .eq(FirePointPlanRelEntity::getPlanId, id)
                .list().stream()
                .distinct()
                .map(FirePointPlanRelEntity::getInspectPointId)
                .collect(Collectors.toList());
        List<FireInspectPlanPointResponse> responseList = new ArrayList<>(relEntityList.size());
        for (Long pointId : relEntityList) {
            FireInspectPointEntity fireInspectPoint = SpringUtil.getBean(FireInspectPointService.class).getBaseMapper().selectById(pointId);
            FireInspectPlanPointResponse fireInspectPlanPointResponse = new FireInspectPlanPointResponse();
            fireInspectPlanPointResponse.setPointId(pointId);
            fireInspectPlanPointResponse.setPlanId(id);
            if (Func.isNotEmpty(fireInspectPoint)){
                fireInspectPlanPointResponse.setPointName(fireInspectPoint.getName());
            }
            fireInspectPlanPointResponse.setAreaName(deviceCategory.getName());
            responseList.add(fireInspectPlanPointResponse);
        }
        response.setResponseList(responseList);
        return R.data(response);
    }

    private  List<FireInspectPlanListResponse> listVO(List<FireInspectPlanEntity> list) {
        return list.stream().map(entity->{
            FireInspectPlanListResponse firePlanResponse = new FireInspectPlanListResponse();
            BeanUtils.copyProperties(entity,firePlanResponse);
            firePlanResponse.setPlanStatusName(PlanStatusEnum.getDescByCode(entity.getPlanStatus()));
            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));
                firePlanResponse.setAreaName(buildAreaName(deviceCategory.getParentId(),deviceCategory.getName(),categoryMap));
            }
            firePlanResponse.setInspectCycleName(PlanCycleEnum.getDescByCode(entity.getInspectCycle()));
            OrgUserInfoRequest userInfoRequest = new OrgUserInfoRequest();
            userInfoRequest.setUserId(entity.getInspectUser());
            List<OrgUserInfoResponse> userInfoResponseList = orgUserClient.findPatrolUser(userInfoRequest).getData();
            if (Func.isNotEmpty(userInfoResponseList)){
                firePlanResponse.setInspectUserName(userInfoResponseList.get(0).getUserName());
            }
            return firePlanResponse;
        }).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;
    }
}
