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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.park.api.dto.fire.fight.CloseDangerReqDTO;
import com.yuchen.saas.park.api.dto.fire.fight.FireFightDangerReqDTO;
import com.yuchen.saas.park.api.dto.fire.fight.FireFightDangerSubmitReqDTO;
import com.yuchen.saas.park.api.dto.work.SaasWorkOrderDto;
import com.yuchen.saas.park.api.entity.fire.fight.SaasParkFireFightDanger;
import com.yuchen.saas.park.api.entity.work.SaasWorkOrder;
import com.yuchen.saas.park.api.enums.fight.DangerStateEnum;
import com.yuchen.saas.park.api.vo.fire.fight.FireFightDangerCountVO;
import com.yuchen.saas.park.api.vo.fire.fight.FireFightDangerVO;
import com.yuchen.saas.park.service.mapper.fire.fight.SaasParkFireFightDangerMapper;
import com.yuchen.saas.park.service.service.fire.fight.ISaasParkFireFightDangerService;
import com.yuchen.saas.park.service.service.work.ISaasWorkOrderService;
import com.yuchen.saas.park.service.util.PageConverterUtils;
import com.yuchen.saas.park.service.util.ParkDateUtils;
import lombok.RequiredArgsConstructor;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseEntity;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.NestPage;
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.utils.Func;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 消防隐患信息表 服务实现类
 * </p>
 *
 * @author zhouhanwei
 * @since 2024-04-29
 */
@Service
@RequiredArgsConstructor
public class SaasParkFireFightDangerServiceImpl extends BaseServiceImpl<SaasParkFireFightDangerMapper, SaasParkFireFightDanger> implements ISaasParkFireFightDangerService {

    private final ISaasWorkOrderService iSaasWorkOrderService;

    @Override
    public NestPage<FireFightDangerVO> findFireFightDangerPage(FireFightDangerReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        Page<FireFightDangerVO> resultPage = new Page<>();

        // 赋值数据
        LambdaQueryWrapper<SaasParkFireFightDanger> lambdaWrapper = Wrappers.lambdaQuery();
        lambdaWrapper.eq(SaasParkFireFightDanger::getCustomerId, contextUser.getCustomerManageId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getProjectId()), SaasParkFireFightDanger::getProjectId, reqDTO.getProjectId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getBusinessId()), SaasParkFireFightDanger::getBusinessId, reqDTO.getBusinessId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getDangerLevel()), SaasParkFireFightDanger::getDangerLevel, reqDTO.getDangerLevel());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getDangerType()), SaasParkFireFightDanger::getDangerType, reqDTO.getDangerType());
        lambdaWrapper.and(Func.isNotEmpty(reqDTO.getDangerTargetCodeOrName()), wrapper -> wrapper
                .like(SaasParkFireFightDanger::getTargetNames, reqDTO.getDangerTargetCodeOrName())
                .or()
                .like(SaasParkFireFightDanger::getTargetCodes, reqDTO.getDangerTargetCodeOrName()));
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getDangerState()), SaasParkFireFightDanger::getDangerState, reqDTO.getDangerState());
        lambdaWrapper.ge(Func.isNotEmpty(reqDTO.getReportStartDate()), SaasParkFireFightDanger::getReportDate, reqDTO.getReportStartDate());
        lambdaWrapper.le(Func.isNotEmpty(reqDTO.getReportEndDate()), SaasParkFireFightDanger::getReportDate, reqDTO.getReportEndDate());
        lambdaWrapper.orderByDesc(BaseEntity::getCreateTime);
        IPage<SaasParkFireFightDanger> page = page(Condition.getPage(reqDTO), lambdaWrapper);
        List<SaasParkFireFightDanger> fireFightDangerList = page.getRecords();

        // 数据列表
        List<FireFightDangerVO> resultList = new ArrayList<>();
        for (SaasParkFireFightDanger saasParkFireFightDanger : fireFightDangerList) {
            FireFightDangerVO vo = new FireFightDangerVO();
            BeanUtil.copyProperties(saasParkFireFightDanger, vo);
            resultList.add(vo);
        }
        resultPage.setTotal(page.getTotal());
        resultPage.setSize(page.getSize());
        resultPage.setCurrent(page.getCurrent());
        resultPage.setRecords(resultList);
        return PageConverterUtils.convert(resultPage);
    }

    @Override
    public FireFightDangerCountVO getFireFightDangerCount(FireFightDangerReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        // 分页数据
        reqDTO.setCurrent(-1);
        reqDTO.setSize(-1);
        // 赋值数据
        NestPage<FireFightDangerVO> page = findFireFightDangerPage(reqDTO);
        List<FireFightDangerVO> fireFightDangerList = page.getRecords();

        FireFightDangerCountVO countVO = new FireFightDangerCountVO();
        countVO.setAllDangerSum((long) fireFightDangerList.size());
        // 待处理数
        Long toProcessDangerSum = fireFightDangerList.stream().filter(s ->
                StrUtil.equals(DangerStateEnum.TO_PROCESS.getCode(), s.getDangerState())).count();
        countVO.setToProcessDangerSum(toProcessDangerSum);
        // 处理中数
        Long inProcessDangerSum = fireFightDangerList.stream().filter(s ->
                StrUtil.equals(DangerStateEnum.IN_PROCESS.getCode(), s.getDangerState())).count();
        countVO.setInProcessDangerSum(inProcessDangerSum);
        // 已处理数
        Long ProcessedDangerSum = fireFightDangerList.stream().filter(s ->
                StrUtil.equals(DangerStateEnum.PROCESSED.getCode(), s.getDangerState())).count();
        countVO.setProcessedDangerSum(ProcessedDangerSum);
        // 已关闭数
        Long closeDangerSum = fireFightDangerList.stream().filter(s ->
                StrUtil.equals(DangerStateEnum.ClOSE.getCode(), s.getDangerState())).count();
        countVO.setCloseDangerSum(closeDangerSum);

        Date newDate = new Date();
        // 本月隐患数
        int currentMonth = ParkDateUtils.getCurrentMonth(newDate);
        List<FireFightDangerVO> currentMonthFireFightDangerList = fireFightDangerList.stream().filter(s ->
                currentMonth == ParkDateUtils.getCurrentMonth(s.getReportDate())).collect(Collectors.toList());
        countVO.setCurrentMonthDangerSum((long) currentMonthFireFightDangerList.size());
        // 上月隐患数
        int lastMonth = ParkDateUtils.getLastMonth(newDate);
        List<FireFightDangerVO> lastMonthFireFightDangerList = fireFightDangerList.stream().filter(s ->
                lastMonth == ParkDateUtils.getCurrentMonth(s.getReportDate())).collect(Collectors.toList());
        countVO.setLastMonthDangerSum((long) lastMonthFireFightDangerList.size());
        // 上年同月隐患数
        int lastYear = ParkDateUtils.getLastYear(newDate);
        List<FireFightDangerVO> lastYearCurrentFireFightDangerList = fireFightDangerList.stream().filter(s ->
                lastYear == ParkDateUtils.getLastYear(s.getReportDate())
                        && currentMonth == ParkDateUtils.getCurrentMonth(s.getReportDate())).collect(Collectors.toList());
        countVO.setLastYearCurrentMonthDangerSum((long) lastYearCurrentFireFightDangerList.size());
        return countVO;
    }

    @Override
    public FireFightDangerVO getFireFightDanger(Long dangerId) {
        FireFightDangerVO vo = new FireFightDangerVO();
        SaasParkFireFightDanger saasParkFireFightDanger = getById(dangerId);
        if (Objects.isNull(saasParkFireFightDanger)) {
            throw new ServiceException("消防隐患数据不存在");
        }
        BeanUtil.copyProperties(saasParkFireFightDanger, vo);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean closeFireFightDanger(CloseDangerReqDTO reqDTO) {
        SaasParkFireFightDanger saasParkFireFightDanger = getById(reqDTO.getDangerId());
        if (Objects.isNull(saasParkFireFightDanger)) {
            throw new ServiceException("消防隐患数据不存在");
        }
        if (StrUtil.equals(DangerStateEnum.PROCESSED.getCode(), saasParkFireFightDanger.getDangerState())) {
            throw new ServiceException("消防隐患数据已处理，不可关闭");
        }
        if (StrUtil.equals(DangerStateEnum.ClOSE.getCode(), saasParkFireFightDanger.getDangerState())) {
            throw new ServiceException("消防隐患数据已关闭，无需重复关闭");
        }
        saasParkFireFightDanger.setCloseReason(reqDTO.getCloseReason());
        saasParkFireFightDanger.setCloseDesc(reqDTO.getCloseDesc());
        saasParkFireFightDanger.setDangerState(DangerStateEnum.ClOSE.getCode());
        return updateById(saasParkFireFightDanger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addFireFightDanger(FireFightDangerSubmitReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        SaasParkFireFightDanger saasParkFireFightDanger = new SaasParkFireFightDanger();
        BeanUtil.copyProperties(reqDTO, saasParkFireFightDanger);
        saasParkFireFightDanger.setReportDate(new Date());
        saasParkFireFightDanger.setReportOrgUserId(contextUser.getOrgUserId());
        saasParkFireFightDanger.setCustomerId(contextUser.getCustomerManageId());
        saasParkFireFightDanger.setCreateOrgUser(contextUser.getOrgUserId());
        saasParkFireFightDanger.setDangerState(DangerStateEnum.TO_PROCESS.getCode());
        return save(saasParkFireFightDanger);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addDangerWorkOrder(SaasWorkOrderDto workOrderDto, Long dangerId) {
        SaasParkFireFightDanger saasParkFireFightDanger = getById(dangerId);
        if (Objects.isNull(saasParkFireFightDanger)) {
            throw new ServiceException("消防隐患数据不存在");
        }
        // 创建工单
        SaasWorkOrder saasWorkOrder = iSaasWorkOrderService.add(workOrderDto);
        if (Objects.isNull(saasWorkOrder)) {
            throw new ServiceException("维修工单信息不正确");
        }
        saasParkFireFightDanger.setDangerState(DangerStateEnum.IN_PROCESS.getCode());
        return updateById(saasParkFireFightDanger);
    }
}
