package com.casic.missiles.service.Impl.equipment;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.casic.missiles.core.base.service.IBaseExportService;
import com.casic.missiles.core.page.PageFactory;
import com.casic.missiles.dto.ReturnDTO;
import com.casic.missiles.dto.ReturnUtil;
import com.casic.missiles.dto.equipment.RemindQuantityDTO;
import com.casic.missiles.dto.equipment.StandardEquipmentRequest;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.enums.ExportEnum;
import com.casic.missiles.enums.PrefixCodeEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.equipment.*;
import com.casic.missiles.model.equipment.*;
import com.casic.missiles.model.page.PageQuery;
import com.casic.missiles.service.equipment.*;
import com.casic.missiles.utils.DictCodeUtils;
import com.casic.missiles.utils.NumberGeneratorUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 标准装置表 服务实现类
 * </p>
 *
 * @author cuicheng
 * @since 2022-12-15
 */
@Service
public class EquipmentStandardEquipmentServiceImpl extends ServiceImpl<EquipmentStandardEquipmentMapper, EquipmentStandardEquipment> implements IEquipmentStandardEquipmentService {

    @Autowired(required = false)
    private EquipmentStandardEquipmentMapper meterStandardEquipmentMapper;

    @Autowired(required = false)
    private EquipmentStandardEquipmentFileMapper meterStandardEquipmentFileMapper;

    @Autowired
    private IEquipmentStandardEquipmentFileService meterStandardEquipmentFileService;

    @Resource
    private IBaseExportService iBaseExportService;

    @Resource
    private EquipmentStandardEquipmentUserMapper equipmentUserMapper;

    @Resource
    private EquipmentStandardSupportMapper supportMapper;

    @Resource
    private EquipmentStandardVerifyRegulationMapper verifyRegulationMapper;

    @Resource
    private IEquipmentStandardEquipmentUserService equipmentUserService;

    @Resource
    private IEquipmentStandardSupportEquipmentService supportEquipmentService;

    @Resource
    private IEquipmentStandardVerifyRegulationService verifyRegulationService;

    @Value("${casic.meter.standardEquipment.delayDay:30}")
    private Integer delayDay;

    @Override
    public Page<EquipmentStandardEquipment> listPage(Page<EquipmentStandardEquipment> page, StandardEquipmentRequest request) throws Exception {
        Page<EquipmentStandardEquipment> resultPage = meterStandardEquipmentMapper.listPage(page, request);
        for (EquipmentStandardEquipment item:resultPage.getRecords()) {
            DictCodeUtils.convertDictCodeToName(item);
        }
        return resultPage;
    }

    @Override
    @Transactional
    public ReturnDTO add(EquipmentStandardEquipment meterStandardEquipment) {
        //生成资产编号
        Long maxNo = meterStandardEquipmentMapper.selectMaxNo();
        String standard_no = NumberGeneratorUtil.getContactNo(PrefixCodeEnum.STANDARD_EQUIPMENT, maxNo);
        meterStandardEquipment.setStandardNo(standard_no);
        if(meterStandardEquipmentMapper.insert(meterStandardEquipment)>0){
            batchSaveAssociatedTable(meterStandardEquipment);
            return ReturnUtil.success(meterStandardEquipment.getId());
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    public ReturnDTO deleteById(Long id) {
        int deleteFlag = meterStandardEquipmentMapper.deleteById(id);
        if (deleteFlag > 0) {
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    @Override
    @Transactional
    public ReturnDTO update(EquipmentStandardEquipment meterStandardEquipment) {
        // 修改标准装置基本信息
        int updateFlag = meterStandardEquipmentMapper.updateById(meterStandardEquipment);
        if (updateFlag > 0) {
            // 修改关联子表信息
            batchSaveAssociatedTable(meterStandardEquipment);
            return ReturnUtil.success();
        }
        throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
    }

    /**
     * 列表
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public List<EquipmentStandardEquipment> list(StandardEquipmentRequest request) throws Exception {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNo(0);
        pageQuery.setPageSize(10000);
        Page<EquipmentStandardEquipment> page = PageFactory.createPage(pageQuery);
        Page<EquipmentStandardEquipment> resultPage = meterStandardEquipmentMapper.listPage(page, request);
        for (EquipmentStandardEquipment item:resultPage.getRecords()) {
            DictCodeUtils.convertDictCodeToName(item);
        }
        return resultPage.getRecords();
    }

    @Override
    public ReturnDTO addList(List<EquipmentStandardEquipment> meterStandardEquipmentList) throws Exception {
        Long maxNo = meterStandardEquipmentMapper.selectMaxNo();
        for (EquipmentStandardEquipment item:meterStandardEquipmentList) {
            Set<ConstraintViolation<EquipmentStandardEquipment>> validate = Validation.buildDefaultValidatorFactory().getValidator().validate(item);
            if (!CollectionUtils.isEmpty(validate)) {
                return ReturnUtil.failed(validate.iterator().next().getMessage());
            }
            DictCodeUtils.validDictCode(item);
            //生成资产编号
            String standard_no = NumberGeneratorUtil.getContactNo(PrefixCodeEnum.STANDARD_EQUIPMENT, maxNo);
            item.setStandardNo(standard_no);
            maxNo++;
        }
        super.saveBatch(meterStandardEquipmentList);
        return ReturnUtil.success();
    }

    @Override
    public EquipmentStandardEquipment getById(Long id) throws Exception {
        StandardEquipmentRequest request = new StandardEquipmentRequest();
        request.setId(id);
        EquipmentStandardEquipment standardEquipment = meterStandardEquipmentMapper.listPage(request);
        DictCodeUtils.convertDictCodeToName(standardEquipment);
        QueryWrapper<EquipmentStandardEquipmentFile> wrapper = new QueryWrapper<>();
        wrapper.eq("standard_id", id);
        // 获取关联的文件表
        standardEquipment.setFileList(meterStandardEquipmentFileMapper.selectList(wrapper));
        // 获取关联的计量人员
        standardEquipment.setUserList(equipmentUserService.list(id));
        // 获取关联的设备表
        standardEquipment.setEquipmentList(supportEquipmentService.list(id));
        // 获取关联的检定规程表
        standardEquipment.setVerifyRegulationList(verifyRegulationService.list(id));
        return standardEquipment;
    }


    /**
     *
     * @param meterStandardEquipment
     */
    public void batchSaveAssociatedTable(EquipmentStandardEquipment meterStandardEquipment) {
        Long equipmentId = meterStandardEquipment.getId();
        if (!CollectionUtils.isEmpty(meterStandardEquipment.getFileList())) {
            // 删除老的文件，更新新的文件
            QueryWrapper<EquipmentStandardEquipmentFile> wrapper = new QueryWrapper<>();
            wrapper.eq("standard_id", equipmentId);
            meterStandardEquipmentFileMapper.delete(wrapper);
            for (EquipmentStandardEquipmentFile file : meterStandardEquipment.getFileList()) {
                file.setStandardId(equipmentId);
            }
            if(!meterStandardEquipmentFileService.saveBatch(meterStandardEquipment.getFileList())){
                throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            }
        }
        if (!CollectionUtils.isEmpty(meterStandardEquipment.getUserList())) {
            // 删除之前关联的人员，新增最终的人员列表
            QueryWrapper<EquipmentStandardEquipmentUser> wrapper = new QueryWrapper<>();
            wrapper.eq("standard_equipment_id", equipmentId);
            equipmentUserMapper.delete(wrapper);
            for (EquipmentStandardEquipmentUser user : meterStandardEquipment.getUserList()) {
                user.setStandardEquipmentId(equipmentId);
            }
            if(!equipmentUserService.saveBatch(meterStandardEquipment.getUserList())){
                throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            }
        }
        if (!CollectionUtils.isEmpty(meterStandardEquipment.getEquipmentList())) {
            // 删除之前关联的设备，新增最终的设备列表
            QueryWrapper<EquipmentStandardSupportEquipment> wrapper = new QueryWrapper<>();
            wrapper.eq("standard_equipment_id", equipmentId);
            supportMapper.delete(wrapper);
            for (EquipmentStandardSupportEquipment equipment : meterStandardEquipment.getEquipmentList()) {
                equipment.setStandardEquipmentId(equipmentId);
            }
            if(!supportEquipmentService.saveBatch(meterStandardEquipment.getEquipmentList())){
                throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            }
        }
        if (!CollectionUtils.isEmpty(meterStandardEquipment.getVerifyRegulationList())) {
            // 删除之前关联的检定规程，新增最终检定规程列表
            QueryWrapper<EquipmentStandardVerifyRegulation> wrapper = new QueryWrapper<>();
            wrapper.eq("standard_equipment_id", equipmentId);
            verifyRegulationMapper.delete(wrapper);
            for (EquipmentStandardVerifyRegulation verifyRegulation : meterStandardEquipment.getVerifyRegulationList()) {
                verifyRegulation.setStandardEquipmentId(equipmentId);
            }
            if(!verifyRegulationService.saveBatch(meterStandardEquipment.getVerifyRegulationList())){
                throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED);
            }
        }
    }

    @Override
    public Page<EquipmentStandardEquipment> remindListPage(Page<EquipmentStandardEquipment> page, StandardEquipmentRequest request) throws Exception {
        Page<EquipmentStandardEquipment> resultPage = meterStandardEquipmentMapper.remindListPage(page, request);
        for (EquipmentStandardEquipment item:resultPage.getRecords()) {
            DictCodeUtils.convertDictCodeToName(item);
        }
        return resultPage;
    }

    @Override
    public RemindQuantityDTO remindQuantity() {
        Integer remindQuantity = meterStandardEquipmentMapper.selectRemindQuantity();
        RemindQuantityDTO result = new RemindQuantityDTO();
        result.setRemindQuantity(remindQuantity);
        return result;
    }

    /**
     * 删除：提醒时间=当前时间+30[配置值：推迟时间]天
     * todo： 新增、更新标准装置时，设置默认提醒时间（有效时间+30[配置值：提醒时间]天）
     * @param id 标准装置id
     * @return 更新结果
     */
    @Override
    public ReturnDTO deleteRemind(Long id) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,delayDay);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        return updateRemindTime(id, calendar.getTime());
    }

    /**
     * 提醒：提醒时间=当前时间
     * @param id 标准装置id
     * @return 更新结果
     */
    @Override
    public ReturnDTO remind(Long id) {

        // todo 依赖质量管理里的溯源的证书管理，需要完善
        return updateRemindTime(id,new Date());
    }

    @Override
    public void exportRemindList(HttpServletResponse response, StandardEquipmentRequest request) throws Exception {
        List<EquipmentStandardEquipment> list;
        // 判断是否为通过ids导出
        if(!CollectionUtils.isEmpty(request.getIds())){
            StandardEquipmentRequest equipmentRequest = new StandardEquipmentRequest();
            equipmentRequest.setIds(request.getIds());
            list = meterStandardEquipmentMapper.remindListPage(equipmentRequest);
        }else{
            list = meterStandardEquipmentMapper.remindListPage(request);
        }
        for (EquipmentStandardEquipment item:list) {
            DictCodeUtils.convertDictCodeToName(item);
        }
        iBaseExportService.exportExcel(response, EquipmentStandardEquipment.class,list, ExportEnum.STANDARD_EQUIPMENT_REMIND.getSheetName());
    }

    @NotNull
    private ReturnDTO updateRemindTime(Long id, Date remind_time) {
        UpdateWrapper<EquipmentStandardEquipment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id).set("remind_time", remind_time);
        if(meterStandardEquipmentMapper.update(null, updateWrapper)>0){
            return ReturnUtil.success();
        }
        return ReturnUtil.failed("操作失败");
    }

}
