package org.dromara.inspection.service.impl;

import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.inspection.domain.OpsInspectionNode;
import org.dromara.inspection.domain.bo.OpsInspectionRepairBo;
import org.dromara.inspection.domain.vo.*;
import org.dromara.inspection.mapper.OpsInspectionNodeMapper;
import org.dromara.personnel.domain.vo.OpsUserVo;
import org.dromara.personnel.mapper.OpsUserMapper;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.vo.RemoteUserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.inspection.domain.bo.OpsInspectionOrderBo;
import org.dromara.inspection.domain.OpsInspectionOrder;
import org.dromara.inspection.mapper.OpsInspectionOrderMapper;
import org.dromara.inspection.service.IOpsInspectionOrderService;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 运维-巡检-工单Service业务层处理
 *
 * @author LionLi
 * @date 2025-09-23
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpsInspectionOrderServiceImpl implements IOpsInspectionOrderService {


    private final OpsInspectionOrderMapper baseMapper;

    private final OpsInspectionNodeMapper nodeMapper;

    @DubboReference
    private RemoteFileService remoteFileService;
    @DubboReference
    private RemoteUserService remoteUserService;

    /**
     * 查询运维-巡检-工单
     *
     * @param id 主键
     * @return 运维-巡检-工单
     */
    @Override
    public OpsInspectionOrderVo queryById(Long id){
        OpsInspectionOrderVo opsInspectionOrderVo = baseMapper.selectVoById(id);
        List<OpsInspectionOrderVo> opsInspectionOrderVo1 = List.of(opsInspectionOrderVo);
        setValue(opsInspectionOrderVo1);
        return opsInspectionOrderVo1.getFirst();
    }

    /**
     * 分页查询运维-巡检-工单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 运维-巡检-工单分页列表
     */
    @Override
    public TableDataInfo<OpsInspectionOrderVo> queryPageList(OpsInspectionOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OpsInspectionOrder> lqw = buildQueryWrapper(bo);
        Page<OpsInspectionOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        setValue(result.getRecords());
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的运维-巡检-工单列表
     *
     * @param bo 查询条件
     * @return 运维-巡检-工单列表
     */
    @Override
    public List<OpsInspectionOrderVo> queryList(OpsInspectionOrderBo bo) {
        LambdaQueryWrapper<OpsInspectionOrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OpsInspectionOrder> buildQueryWrapper(OpsInspectionOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OpsInspectionOrder> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(OpsInspectionOrder::getId);
        lqw.eq(bo.getProjectId() != null, OpsInspectionOrder::getProjectId, bo.getProjectId());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), OpsInspectionOrder::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getLevel()), OpsInspectionOrder::getLevel, bo.getLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getPoint()), OpsInspectionOrder::getPoint, bo.getPoint());
        lqw.eq(bo.getCreateTime() != null, OpsInspectionOrder::getCreateTime, bo.getCreateTime());
        return lqw;
    }

    /**
     * 新增运维-巡检-工单
     *
     * @param bo 运维-巡检-工单
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OpsInspectionOrderBo bo) {
        OpsInspectionOrder add = MapstructUtils.convert(bo, OpsInspectionOrder.class);
        validEntityBeforeSave(add);

        if (add.getFileId() != null){
            String[] split = add.getFileId().split(",");
            List<String> urls = new ArrayList<>();
            for (String s : split) {
                String ossUrl = remoteFileService.selectUrlByIds(s);
                if (ossUrl != null){
                    urls.add(ossUrl);
                }
            }
            String join = String.join(",", urls);
            add.setFileUrl(join);
            bo.setFileUrl(join);
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改运维-巡检-工单
     *
     * @param bo 运维-巡检-工单
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(OpsInspectionOrderBo bo) {
        OpsInspectionOrder update = MapstructUtils.convert(bo, OpsInspectionOrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OpsInspectionOrder entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除运维-巡检-工单信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }

        List<String> urls = new ArrayList<>();
        List<Long> nodeIds = new ArrayList<>();

        for (Long id : ids) {
            OpsInspectionOrderVo vo = queryById(id);
            if (vo != null){
                if (vo.getFileUrl()!=null) {
                    urls.add(vo.getFileUrl());
                }
                for (String nodeId : List.of(vo.getNodeIds().split(","))) {
                    nodeIds.add(Long.valueOf(nodeId));
                }
            }
        }

        if (!urls.isEmpty()) {
            for (String url : urls) {
                List<String> list = Arrays.asList(url.split(","));
                remoteFileService.deleteFile(list);
            }
        }

        //同时删除节点
        if (!nodeIds.isEmpty()) {
            nodeMapper.deleteByIds(nodeIds);
        }

        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 处理回显数据
     */
    private void setValue(List<OpsInspectionOrderVo> list){

        LambdaQueryWrapper<OpsInspectionNode> nodeWrapper = new LambdaQueryWrapper<>();

        for (OpsInspectionOrderVo vo : list) {

            List<String> split = Arrays.stream(vo.getNodeIds().split(",")).toList();

            nodeWrapper.clear();
            nodeWrapper.in(OpsInspectionNode::getId, split);

            List<OpsInspectionNodeVo> nodeVoList = nodeMapper.selectVoList(nodeWrapper);

            //处理进度百分比 完成节点 / 总节点 * 100
            if (nodeVoList != null && !nodeVoList.isEmpty()){
                //统计完成节点
                int finishCount = nodeVoList.stream().filter(nodeVo -> nodeVo.getStatus().equals("1")).toList().size();
                if (finishCount == nodeVoList.size()){
                    vo.setProgress(new BigDecimal("100"));
                }else {
                    vo.setProgress(BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(nodeVoList.size()), 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100.00)));
                }
            }

            //处理派单人
            List<RemoteUserVo> remoteUserVos = remoteUserService.selectListByIds(List.of(vo.getCreateBy()));
            if (remoteUserVos !=  null && !remoteUserVos.isEmpty()){
                vo.setSendOrderPersonVo(remoteUserVos.getFirst());
            }

            //处理接单人
            if (vo.getGetOrderPerson() != null){
                remoteUserVos = remoteUserService.selectListByIds(Collections.singletonList(vo.getGetOrderPerson()));
                if (remoteUserVos !=  null && !remoteUserVos.isEmpty()){
                    vo.setGetOrderPersonVo(remoteUserVos.getFirst());
                }
            }

            //处理节点列表
            if (vo.getNodeIds() != null && !vo.getNodeIds().isEmpty()){
                String[] ids = vo.getNodeIds().split(",");
                List<OpsInspectionNodeVo> nodeVos = new ArrayList<>();
                for (String id : ids) {
                    OpsInspectionNodeVo nodeVo = nodeMapper.selectVoById(id);
                    if (nodeVo != null) {
                        nodeVos.add(nodeVo);
                    }
                }
                vo.setNodes(nodeVos);
            }

        }
    }

    /**
     * 获取纪录
     */
    public R<OrderRecordVo> record(Long projectId){
        //变量初始化
        OrderRecordVo recordVo = new OrderRecordVo();

        OpsInspectionOrderBo bo = new OpsInspectionOrderBo();
        bo.setProjectId(projectId);
        //日期初始化
        Date startDate = Date.from(LocalDate.now().withDayOfMonth(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(LocalDate.now().withDayOfMonth(1).plusMonths(1).minusDays(1).atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());
        //查询当前项目的数据
        List<OpsInspectionOrderVo> vos = queryList(bo);
        //过滤本月数据
        List<OpsInspectionOrderVo> thisMonth = vos.stream()
            .filter(vo -> vo.getCreateTime().after(startDate))
            .filter(vo -> vo.getCreateTime().before(endDate))
            .toList();
        //本月派单总数
        BigDecimal bypdzs = BigDecimal.valueOf(thisMonth.size());
        //统计平均响应时间
        Long zgxysj = 0L;//总共响应时间
        Long jds = 0L;//本月接单数 有接单才有响应时间
        for (OpsInspectionOrderVo orderVo : thisMonth) {
            if (orderVo.getGetOrderTime() != null) {
                jds++;
                zgxysj += orderVo.getGetOrderTime().getTime() - orderVo.getCreateTime().getTime();
            }
        }
        //平均响应时间
        BigDecimal avg;
        if ((BigDecimal.valueOf(jds).compareTo(BigDecimal.ZERO) > 0)) {
            avg = BigDecimal.valueOf(TimeUnit.MILLISECONDS.toMinutes(zgxysj)).divide(BigDecimal.valueOf(jds), 2, RoundingMode.HALF_UP);
        }else{
            avg = BigDecimal.ZERO;
        }
        //统计待接收工单
        int waiting = thisMonth.stream().filter(vo -> vo.getStatus().equals("2")).toList().size();
        //待接单数
        BigDecimal djds = BigDecimal.valueOf(waiting);
        //按时完成率 找到完成的工单 获取工单完成时间

        //获取所有完成数
        int sywcs = thisMonth.stream()
            .filter(vo -> vo.getStatus().equals("4"))
            .toList().size();

        //获取按时完成数
        int aswcs = thisMonth.stream()
            .filter(vo -> vo.getStatus().equals("4"))
            .filter(vo -> vo.getFinishiOrderTime().before(endDate))
            .toList().size();
        //按时完成率
        BigDecimal aswcl;
        if (sywcs > 0) {
            aswcl = BigDecimal.valueOf(aswcs).divide(BigDecimal.valueOf(sywcs), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100.00));
        }else {
            aswcl = BigDecimal.valueOf(0);
        }

        recordVo.setBypds(String.valueOf(bypdzs));
        recordVo.setPjxysj(String.valueOf(avg));
        recordVo.setDjsgd(String.valueOf(djds));
        recordVo.setAswcl(String.valueOf(aswcl));

        //获取上月数据列表
        Date finalStartDate = Date.from(LocalDate.now().minusMonths(1).withDayOfMonth(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date finalEndDate = Date.from(LocalDate.now().minusMonths(1).withDayOfMonth(1).plusMonths(1).minusDays(1).atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());

        thisMonth = vos.stream()
            .filter(vo -> vo.getCreateTime().after(finalStartDate))
            .filter(vo -> vo.getCreateTime().before(finalEndDate))
            .toList();

        //上月派单总数
        BigDecimal sypdzs = BigDecimal.valueOf(thisMonth.size());

        //统计上月平均响应时间
        zgxysj = 0L;//总共响应时间
        jds = 0L;//本月接单数 有接单才有响应时间
        for (OpsInspectionOrderVo orderVo : thisMonth) {
            if (orderVo.getGetOrderTime() != null) {
                jds++;
                zgxysj += orderVo.getGetOrderTime().getTime() - orderVo.getCreateTime().getTime();
            }
        }
        //上月平均响应时间
        BigDecimal syavg;
        if ((BigDecimal.valueOf(jds).compareTo(BigDecimal.ZERO) > 0)) {
            syavg = BigDecimal.valueOf(TimeUnit.MILLISECONDS.toMinutes(zgxysj)).divide(BigDecimal.valueOf(jds), 2, RoundingMode.HALF_UP);
        }else {
            syavg = BigDecimal.ZERO;
        }

        //获取上月所有完成数
        int sysywcs = thisMonth.stream()
            .filter(vo -> vo.getStatus().equals("4"))
            .toList().size();

        //获取上月按时完成数
        int syaswcs = thisMonth.stream()
            .filter(vo -> vo.getStatus().equals("4"))
            .filter(vo -> vo.getFinishiOrderTime().before(finalEndDate))
            .toList().size();
        //上月按时完成率
        BigDecimal syaswcl;
        if (sywcs > 0) {
            syaswcl = BigDecimal.valueOf(syaswcs).divide(BigDecimal.valueOf(sysywcs), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100.00));
        }else {
            syaswcl = BigDecimal.valueOf(0);
        }

        //本月完成 / 上月完成 * 100 = 增长率
        BigDecimal wczzl;
        if (syaswcl.compareTo(BigDecimal.ZERO) > 0) {
            wczzl = BigDecimal.valueOf(Double.parseDouble(recordVo.getAswcl())).divide(syaswcl, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }else {
            wczzl = BigDecimal.valueOf(0);
        }

        //上月完成率增长率
        recordVo.setWczzl(wczzl.toString());

        //派单增长率
        BigDecimal pdzzl;
        if (sypdzs.compareTo(BigDecimal.ZERO) > 0) {
            pdzzl = BigDecimal.valueOf(Double.parseDouble(recordVo.getBypds())).divide(sypdzs, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }else {
            pdzzl = BigDecimal.valueOf(0);
        }
        recordVo.setPdzzl(pdzzl.toString());

        //响应时间增长率
        BigDecimal xysjzzl;
        if (BigDecimal.valueOf(Double.parseDouble(recordVo.getPjxysj())).compareTo(BigDecimal.ZERO) > 0){
            xysjzzl = syavg.divide(BigDecimal.valueOf(Double.parseDouble(recordVo.getPjxysj())), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }else {
            xysjzzl = BigDecimal.ZERO;
        }
        recordVo.setXysjzzl(xysjzzl.toString());

        return R.ok(recordVo);
    }

}
