package org.eco.als.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.eco.als.domain.FaultStatistics;
import org.eco.als.domain.bo.FaultStatisticsBo;
import org.eco.als.domain.vo.FaultStatisticsVo;
import org.eco.als.domain.vo.FaultStatisticsWbVo;
import org.eco.als.mapper.FaultStatisticsMapper;
import org.eco.als.service.IFaultStatisticsService;
import org.eco.common.core.core.page.PageResult;
import org.eco.common.core.utils.HttpUtils;
import org.eco.common.core.utils.MapstructUtils;
import org.eco.common.orm.core.page.PageQuery;
import org.eco.common.orm.core.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static org.eco.als.domain.table.FaultStatisticsTableDef.FAULT_STATISTICS;

/**
 * 故障统计Service业务层处理
 *
 * @author wgk
 * @date 2024-12-13
 */
@Service
@Slf4j
public class FaultStatisticsServiceImpl extends BaseServiceImpl<FaultStatisticsMapper, FaultStatistics> implements IFaultStatisticsService {
    @Resource
    private FaultStatisticsMapper faultStatisticsMapper;

    @Value("${extra.wcjw-gztj-url}")
    private String wcjwGztjUrl;

    @Override
    public QueryWrapper query() {
        return super.query().from(FAULT_STATISTICS);
    }

    private QueryWrapper buildQueryWrapper(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(FAULT_STATISTICS.STATISTICS_DATE.eq(faultStatisticsBo.getStatisticsDate()));
        queryWrapper.and(FAULT_STATISTICS.WAR_ZONE.eq(faultStatisticsBo.getWarZone()));

        queryWrapper.and(FAULT_STATISTICS.GROUPS.eq(faultStatisticsBo.getGroups()));
        queryWrapper.and(FAULT_STATISTICS.MAJOR.eq(faultStatisticsBo.getMajor()));
        queryWrapper.and(FAULT_STATISTICS.AIRCRAFT_MODEL.eq(faultStatisticsBo.getAircraftModel()));
        queryWrapper.and(FAULT_STATISTICS.AIRCRAFT_NUM.eq(faultStatisticsBo.getAircraftNum()));
        queryWrapper.and(FAULT_STATISTICS.FAULTY_PARTS_NAME.eq(faultStatisticsBo.getFaultyPartsName()));
        queryWrapper.and(FAULT_STATISTICS.FAULTY_PARTS_NUM.eq(faultStatisticsBo.getFaultyPartsNum()));
        queryWrapper.and(FAULT_STATISTICS.FAULTY_PARTS_MODEL.eq(faultStatisticsBo.getFaultyPartsModel()));

        if (faultStatisticsBo.getStartStatisticsDate() != null && faultStatisticsBo.getEndStatisticsDate() != null) {
            queryWrapper.between("statistics_date", faultStatisticsBo.getStartStatisticsDate(),
                faultStatisticsBo.getEndStatisticsDate());
        }
        if (faultStatisticsBo.getDistinctField() != null) {
            switch (faultStatisticsBo.getDistinctField()) {
                // 指定去重字段
                case "groups" -> queryWrapper.select("DISTINCT groups").where("groups is not null");
                case "major" -> queryWrapper.select("DISTINCT major").where("major is not null");
                case "aircraft_model" -> queryWrapper.select("DISTINCT aircraft_model").where("aircraft_model is not null");
                case "aircraft_num" -> {
                }
                case "faulty_parts_name" -> queryWrapper.select("DISTINCT faulty_parts_name").where("faulty_parts_name is not null");
            }
        }

        return queryWrapper;
    }

    private QueryWrapper buildStatisticsWrapper(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();

        queryWrapper.and(FAULT_STATISTICS.GROUPS.eq(faultStatisticsBo.getGroups()));
        queryWrapper.and(FAULT_STATISTICS.MAJOR.eq(faultStatisticsBo.getMajor()));
        queryWrapper.and(FAULT_STATISTICS.AIRCRAFT_MODEL.eq(faultStatisticsBo.getAircraftModel()));
        queryWrapper.and(FAULT_STATISTICS.AIRCRAFT_NUM.eq(faultStatisticsBo.getAircraftNum()));
        queryWrapper.and(FAULT_STATISTICS.FAULTY_PARTS_NAME.eq(faultStatisticsBo.getFaultyPartsName()));

        if (faultStatisticsBo.getStartStatisticsDate() != null && faultStatisticsBo.getEndStatisticsDate() != null) {
            queryWrapper.between("statistics_date", faultStatisticsBo.getStartStatisticsDate(),
                faultStatisticsBo.getEndStatisticsDate());
        }
        queryWrapper.select("faulty_parts_name,COUNT(*) as name_count").groupBy("faulty_parts_name");

        return queryWrapper;
    }

    /**
     * 查询故障统计
     *
     * @param id 故障统计主键
     * @return 故障统计
     */
    @Override
    public FaultStatisticsVo selectById(Long id) {
        return this.getOneAs(query().where(FAULT_STATISTICS.ID.eq(id)), FaultStatisticsVo.class);

    }


    /**
     * 查询故障统计列表
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 故障统计集合
     */
    @Override
    public List<FaultStatisticsVo> selectList(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(faultStatisticsBo);
        return this.listAs(queryWrapper, FaultStatisticsVo.class);
    }

    /**
     * 查询故障统计数量
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 故障统计集合
     */
    @Override
    public List<FaultStatisticsVo> Statistics(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = buildStatisticsWrapper(faultStatisticsBo);
        return this.listAs(queryWrapper, FaultStatisticsVo.class);
    }

    @Transactional
    @Override
    public void getExtraStatistics() {
        int count = faultStatisticsMapper.deleteByCondition(FAULT_STATISTICS.CREATE_TIME.lt(DateUtil.date()).and(FAULT_STATISTICS.REMARKS.isNull()));
        log.info("删除数据条数：{}", count);
        String pageNo = "1";
        JSONArray rows = getStatisticsData(pageNo);
        while (CollUtil.isNotEmpty(rows)) {
            // 获取下一页的数据
            pageNo = Integer.toString(Integer.parseInt(pageNo) + 1);
            rows = getStatisticsData(pageNo);
        }
    }

    private JSONArray getStatisticsData(String pageNo) {
        Map<String, String> map = new HashMap<>();
        map.put("pager.pageNo", pageNo);
        map.put("pager.pageSize", "1000");
        map.put("identity", "V_KJZB_JWWX_RCDJ_GZXXTJ");
        map.put("sort", "日期");
        map.put("order", "desc nulls last");
        String result = HttpUtils.post(wcjwGztjUrl, map);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        JSONArray rows = jsonObject.getJSONArray("rows");
        List<FaultStatisticsBo> faultStatisticsBos = new ArrayList<>();
        rows.forEach(row -> {
            JSONObject object = JSONUtil.parseObj(row);
            faultStatisticsBos.add(setFaultStatisticsBo(object));
        });
        this.saveBatch(faultStatisticsBos);
        return rows;
    }

    private static FaultStatisticsBo setFaultStatisticsBo(JSONObject object) {
        FaultStatisticsBo faultStatisticsBo = new FaultStatisticsBo();
        faultStatisticsBo.setStatisticsDate(StrUtil.isBlank(object.getStr("日期")) ? null :
            DateUtil.parseDate(object.getStr("日期"))).setWarZone(object.getStr("战区")).setArmy(object.getStr("军")).setDivision(object.getStr("师")).setGroups(object.getStr("团")).setSquadron(object.getStr("中队")).setAircraftNum(object.getStr("飞机号")).setAircraftModel(object.getStr("机型")).setFactoryNum(object.getStr("出厂号码")).setMachineType(object.getStr("机件类型")).setMachineNum(object.getStr("机件号")).setMachineModel(object.getStr("机件型别")).setMachineName(object.getStr("机件名称")).setLandingGear(object.getStr("起落")).setMajor(object.getStr("专业")).setFaultyPartsName(object.getStr("故障件名称")).setFaultyPartsModel(object.getStr("故障件型别")).setFaultyPartsNum(object.getStr("故障件号码")).setEngineModel(object.getStr("发动机型别")).setEngineNum(object.getStr("发动机号码")).setEngineSerialNum(object.getStr("发动机序号")).setFaultyPartsPosition(object.getStr("故障件位置")).setFaultyPhenomenon(object.getStr("故障现象")).setFaultyPlace(object.getStr("故障发生地点")).setFindOpportunity(object.getStr("发现时机")).setSystems(object.getStr("系统")).setTimingType(object.getStr("计时类型")).setFaultyPartsManufacturer(object.getStr("制造厂1")).setFaultyPartsRenovate(object.getStr("翻修厂1")).setInstallationTime(object.getStr("装本机工作时次")).setTotalWorkTime(object.getStr("工作时次1")).setRepairTime(object.getStr("修后时次1")).setReplacementPartsModel(object.getStr("故换件型别")).setReplacementPartsNum(object.getStr("故换件号码")).setReplacementPartsManufacturer(object.getStr("制造厂2")).setReplacementPartsRenovate(object.getStr("翻修厂2")).setReplacementTotalWorkTime(object.getStr("工作时次2")).setReplacementRepairTime(object.getStr("修后时次2")).setFaultyAbnormalCode(object.getStr("故障失常码")).setFaultyPartsInstallDate(StrUtil.isBlank(object.getStr("故障件装机日期")) ? null : DateUtil.parseDate(object.getStr("故障件装机日期"))).setFaultyReason(object.getStr("故障原因")).setFaultyNature(object.getStr("故障性质")).setFaultyResponsibility(object.getStr("故障责任")).setFaultyConsequence(object.getStr("故障后果")).setHandlingSuggestions(object.getStr("处理意见")).setInfluenceFrequency(object.getStr("影响次数")).setErrorFlyFrequency(object.getStr("误飞次数")).setIdentificationMethod(object.getStr("判明方法")).setDiscoveredPeople(object.getStr("发现人")).setExclusionMethod(object.getStr("排除方法")).setExclusionPeople(object.getStr("排故人")).setExaminePeople(object.getStr("审核人")).setExamineTime(StrUtil.isBlank(object.getStr("审核时间")) ? null : DateUtil.parse(object.getStr("审核时间"), DatePattern.NORM_DATETIME_PATTERN)).setExclusionDate(StrUtil.isBlank(object.getStr("排除日期")) ? null : DateUtil.parseDate(object.getStr("排除日期"))).setExclusionWorkTime(object.getStr("排故工时")).setExclusionPeopleNum(object.getStr("排故人数")).setExclusionTime(object.getStr("排故时间")).setIsAchievement(object.getStr("是否立功")).setNeedTestFly(object.getStr("需要试飞")).setRepairStatus(object.getStr("维修状态"));
        return faultStatisticsBo;
    }

    /**
     * 外部查询故障统计列表
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 故障统计集合
     */
    @Override
    public List<FaultStatisticsWbVo> outsideListAll(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(faultStatisticsBo);
        return this.listAs(queryWrapper, FaultStatisticsWbVo.class);
    }

    /**
     * 分页查询故障统计列表
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 分页故障统计集合
     */
    @Override
    public PageResult<FaultStatisticsVo> selectPage(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(faultStatisticsBo);
        Page<FaultStatisticsVo> page = this.pageAs(PageQuery.build(), queryWrapper, FaultStatisticsVo.class);
        return PageResult.build(page);
    }

    @Override
    public PageResult<FaultStatisticsVo> exclusionListPage(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(FAULT_STATISTICS.EXCLUSION_PEOPLE_NUM.isNull());
//        queryWrapper.and("EXCLUSION_TIME = ''");
        Page<FaultStatisticsVo> page = this.pageAs(PageQuery.build(), queryWrapper, FaultStatisticsVo.class);
        return PageResult.build(page);
    }

    @Override
    public List<FaultStatisticsVo> exclusionList(FaultStatisticsBo faultStatisticsBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(FAULT_STATISTICS.EXCLUSION_PEOPLE_NUM.isNull());
        return this.listAs(queryWrapper, FaultStatisticsVo.class);
    }

    /**
     * 新增故障统计
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 结果:true 操作成功，false 操作失败
     */
    @Override
    public boolean insert(FaultStatisticsBo faultStatisticsBo) {
        FaultStatistics faultStatistics = MapstructUtils.convert(faultStatisticsBo, FaultStatistics.class);
        return this.save(faultStatistics);//使用全局配置的雪花算法主键生成器生成ID值
    }

    @Override
    public boolean saveBatch(List<FaultStatisticsBo> faultStatisticsBos) {
        List<FaultStatistics> faultStatisticsList = new ArrayList<>();
        faultStatisticsBos.forEach(faultStatisticsBo -> faultStatisticsList.add(MapstructUtils.convert(faultStatisticsBo, FaultStatistics.class)));
        return this.saveBatch(faultStatisticsList, 100);
    }

    /**
     * 新增故障统计，前台提供主键值，一般用于导入的场合
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 结果:true 操作成功，false 操作失败
     */
    @Override
    public boolean insertWithPk(FaultStatisticsBo faultStatisticsBo) {
        FaultStatistics faultStatistics = MapstructUtils.convert(faultStatisticsBo, FaultStatistics.class);
        return faultStatisticsMapper.insertWithPk(faultStatistics) > 0;//前台传来主键值
    }

    /**
     * 修改故障统计
     *
     * @param faultStatisticsBo 故障统计Bo
     * @return 结果:true 更新成功，false 更新失败
     */
    @Override
    public boolean update(FaultStatisticsBo faultStatisticsBo) {
        FaultStatistics faultStatistics = MapstructUtils.convert(faultStatisticsBo, FaultStatistics.class);
        if (ObjectUtil.isNotNull(faultStatistics) && ObjectUtil.isNotNull(faultStatistics.getId())) {
            return this.updateById(faultStatistics);
        }
        return false;
    }

    /**
     * 批量删除故障统计
     *
     * @param ids 需要删除的故障统计主键集合
     * @return 结果:true 删除成功，false 删除失败
     */
    @Transactional
    @Override
    public boolean deleteByIds(Long[] ids) {
        return this.removeByIds(Arrays.asList(ids));
    }
}
