package org.dromara.inspection.service.impl;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.seata.spring.annotation.GlobalTransactional;
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.inspection.domain.vo.OpsInspectionReportRecordVo;
import org.dromara.personnel.domain.vo.OpsUserVo;
import org.dromara.personnel.service.impl.OpsUserServiceImpl;
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.OpsInspectionReportBo;
import org.dromara.inspection.domain.vo.OpsInspectionReportVo;
import org.dromara.inspection.domain.OpsInspectionReport;
import org.dromara.inspection.mapper.OpsInspectionReportMapper;
import org.dromara.inspection.service.IOpsInspectionReportService;
import org.springframework.web.multipart.MultipartFile;

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-22
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpsInspectionReportServiceImpl implements IOpsInspectionReportService {

    private final OpsInspectionReportMapper baseMapper;

    @DubboReference
    private RemoteFileService remoteFileService;
    @DubboReference
    private RemoteUserService userService;

    /**
     * 查询运维-巡检-报修
     *
     * @param id 主键
     * @return 运维-巡检-报修
     */
    @Override
    public OpsInspectionReportVo queryById(Long id){
        OpsInspectionReportVo opsInspectionReportVo = baseMapper.selectVoById(id);
        List<OpsInspectionReportVo> opsInspectionReportVo1 = List.of(opsInspectionReportVo);
        setValue(opsInspectionReportVo1);
        return opsInspectionReportVo1.getFirst();
    }

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

    /**
     * 查询符合条件的运维-巡检-报修列表
     *
     * @param bo 查询条件
     * @return 运维-巡检-报修列表
     */
    @Override
    public List<OpsInspectionReportVo> queryList(OpsInspectionReportBo bo) {
        LambdaQueryWrapper<OpsInspectionReport> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OpsInspectionReport> buildQueryWrapper(OpsInspectionReportBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OpsInspectionReport> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(OpsInspectionReport::getId);
        lqw.eq(bo.getProjectId() != null, OpsInspectionReport::getProjectId, bo.getProjectId());
        lqw.eq(StringUtils.isNotBlank(bo.getLevel()), OpsInspectionReport::getLevel, bo.getLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OpsInspectionReport::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), OpsInspectionReport::getType, bo.getType());
        lqw.like(StringUtils.isNotBlank(bo.getName()), OpsInspectionReport::getName, bo.getName());
        lqw.eq(bo.getSendPerson() != null, OpsInspectionReport::getSendPerson, bo.getSendPerson());
        lqw.eq(StringUtils.isNotBlank(bo.getReportInfo()), OpsInspectionReport::getReportInfo, bo.getReportInfo());
        lqw.eq(StringUtils.isNotBlank(bo.getPosition()), OpsInspectionReport::getPosition, bo.getPosition());
        lqw.eq(bo.getFileId() != null, OpsInspectionReport::getFileId, bo.getFileId());
        lqw.eq(StringUtils.isNotBlank(bo.getFileUrl()), OpsInspectionReport::getFileUrl, bo.getFileUrl());
        lqw.like(StringUtils.isNotBlank(bo.getReportName()), OpsInspectionReport::getReportName, bo.getReportName());
        lqw.eq(StringUtils.isNotBlank(bo.getReportPhone()), OpsInspectionReport::getReportPhone, bo.getReportPhone());
        return lqw;
    }

    /**
     * 新增运维-巡检-报修
     *
     * @param bo 运维-巡检-报修
     * @return 是否新增成功
     */
    @Override
    @GlobalTransactional
    public Boolean insertByBo(OpsInspectionReportBo bo) {
        OpsInspectionReport add = MapstructUtils.convert(bo, OpsInspectionReport.class);
        validEntityBeforeSave(add);

        if (add ==  null){
            return false;
        }

        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(OpsInspectionReportBo bo) {
        OpsInspectionReport update = MapstructUtils.convert(bo, OpsInspectionReport.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

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

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

        List<String> urls = new ArrayList<>();
        for (Long id : ids) {
            OpsInspectionReportVo opsInspectionReportVo = queryById(id);
            if (opsInspectionReportVo != null){
                if (opsInspectionReportVo.getFileUrl()!=null) {
                    urls.add(opsInspectionReportVo.getFileUrl());
                }
            }
        }

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

        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 处理回显数据
     */
    private void setValue(List<OpsInspectionReportVo> list){
        if (list == null || list.isEmpty()){
            return;
        }

        for (OpsInspectionReportVo vo : list) {

            if (vo.getSendPerson() == null){
                continue;
            }

            List<RemoteUserVo> remoteUserVos = userService.selectListByIds(Collections.singletonList(vo.getSendPerson()));
            if (remoteUserVos == null || remoteUserVos.isEmpty()){
                continue;
            }

            vo.setSendPersonVo(remoteUserVos.getFirst());

            remoteUserVos =  userService.selectListByIds(Collections.singletonList(vo.getCreateBy()));
            if (remoteUserVos != null && !remoteUserVos.isEmpty()){
                if (remoteUserVos.getFirst().getUserName()!=null) {
                    vo.setName(remoteUserVos.getFirst().getUserName());
                }
                if (remoteUserVos.getFirst().getPhonenumber()!=null){
                    vo.setReportPhone(remoteUserVos.getFirst().getPhonenumber());
                }
            }
        }
    }

    public R<OpsInspectionReportRecordVo> record(Long projectId) {
        //变量初始化
        OpsInspectionReportRecordVo recordVo = new OpsInspectionReportRecordVo();
        OpsInspectionReportBo bo = new OpsInspectionReportBo();
        bo.setProjectId(projectId);
        //日期初始化
        LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
        LocalDate lastDay = firstDay.plusMonths(1).minusDays(1);
        Date startDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());
        //查询当前项目的报修数据
        List<OpsInspectionReportVo> opsInspectionReportVos = queryList(bo);

        //过滤本月数据
        List<OpsInspectionReportVo> thisMonth = opsInspectionReportVos.stream()
            .filter(vo -> vo.getCreateTime().after(startDate))
            .filter(vo -> vo.getCreateTime().before(endDate))
            .toList();
        //本月总报修数
        recordVo.setByzbxs(String.valueOf(thisMonth.size()));

        //平均处理时长    完成时间-创建时间 转为 分钟 / 总报
        Long time = 0L;//总共完成时间
        for (OpsInspectionReportVo vo : thisMonth) {
            if (vo.getStatus().equals("3")){
                time += vo.getReportFinishTime().getTime() - vo.getCreateTime().getTime();
            }
        }
        time = TimeUnit.MILLISECONDS.toMinutes(time);
        BigDecimal divide1 = BigDecimal.valueOf(time).divide(BigDecimal.valueOf(thisMonth.size()), 0, RoundingMode.HALF_UP);
        long hours = TimeUnit.MINUTES.toHours(Long.parseLong(divide1.toString()));

        //平均处理时长
        recordVo.setPjclsc(Long.toString(hours));

        //待处理报修
        int size = thisMonth.stream().filter(vo -> vo.getStatus().equals("1")).toList().size();
        recordVo.setDclbx(String.valueOf(size));

        //完成率
        //完成数
        int finishCount = thisMonth.stream().filter(vo -> vo.getStatus().equals("3")).toList().size();
        BigDecimal divide = BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(thisMonth.size()), 2, RoundingMode.HALF_UP);
        recordVo.setWcl(divide.multiply(new BigDecimal("100")).toString());

        //统计上一月的数据
        firstDay = LocalDate.now().minusMonths(1).withDayOfMonth(1);
        lastDay = firstDay.plusMonths(1).minusDays(1);
        Date finalStartDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date finalEndDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());


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

        //上一月总报修数
        Long lastMonth = (long) thisMonth.size();
        //上一月平均处理时长
        BigDecimal avg;
        time = 0L;
        for (OpsInspectionReportVo vo : thisMonth) {
            if (vo.getStatus().equals("3")){
                time += vo.getReportFinishTime().getTime() - vo.getCreateTime().getTime();
            }
        }
        time = TimeUnit.MILLISECONDS.toMinutes(time);

        if (thisMonth.isEmpty()){
            avg = BigDecimal.ZERO;
        }else {
            avg = BigDecimal.valueOf(time).divide(BigDecimal.valueOf(thisMonth.size()),2, RoundingMode.HALF_UP);
        }
        //上一月完成率
        finishCount = thisMonth.stream().filter(vo -> vo.getStatus().equals("3")).toList().size();

        if (!thisMonth.isEmpty()) {
            divide = BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(thisMonth.size()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
        }else {
            divide = BigDecimal.ZERO;
        }

        //总报修数增长率
        BigDecimal multiply;
        if (lastMonth != 0) {
            multiply = BigDecimal.valueOf(Long.parseLong(recordVo.getByzbxs())).divide(BigDecimal.valueOf(lastMonth), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }else {
            multiply = BigDecimal.ZERO;
        }
        recordVo.setBxsjszzzl(multiply.toString());

        //平均处理时长增长率 本月 / 上月 * 100
        if (!avg.equals(BigDecimal.ZERO)) {
            recordVo.setClscjszzzl(BigDecimal.valueOf(Long.parseLong(recordVo.getPjclsc())).divide(avg, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).toString());
        }else{
            recordVo.setClscjszzzl("0");
        }

        //完成率增长率 本月 / 上月 * 100
        if (!divide.equals(BigDecimal.ZERO)) {
            recordVo.setWcljszzzl(BigDecimal.valueOf(Long.parseLong(recordVo.getWcl())).divide(divide, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).toString());
        }else {
            recordVo.setWcljszzzl("0");
        }
        return R.ok(recordVo);
    }

}
