package com.gci.boot.modules.vehicles.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.ObjectUtil;
import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord;
import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper;
import com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gci.boot.annotation.Query.handle.QueryGenerator;
import com.gci.boot.common.util.BeanUtilsCopy;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.common.util.Lock;
import com.gci.boot.constant.CommonConstant;
import com.gci.boot.modules.vehicles.entity.TbInsurance;
import com.gci.boot.modules.vehicles.entity.TbInsuranceRemind;
import com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper;
import com.gci.boot.modules.vehicles.service.ITbInsuranceRemindService;
import com.gci.boot.modules.vehicles.service.ITbInsuranceService;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 保险提醒 服务实现类
 * </p>
 *
 * @author xushuhan
 * @since 2023-11-07
 */
@Slf4j
@Service
public class TbInsuranceRemindServiceImpl extends ServiceImpl<TbInsuranceRemindMapper, TbInsuranceRemind> implements ITbInsuranceRemindService {

	@Autowired
	private TbInsuranceMapper tbInsuranceMapper;
	@Autowired
	private TbInsuranceRecordMapper tbInsuranceRecordMapper;
    @Autowired
    private Lock lock;

    @Override
	public void createRemind() {
		Map<String, TbInsurance> remindMap = getInsurance();
		List<TbInsuranceRemind> list = list();
		Map<String,TbInsuranceRemind> map = new HashMap<>();
		for (TbInsuranceRemind tbInsurance : list) {
			map.put(tbInsurance.getInsuranceId(), tbInsurance);
		}
		List<TbInsuranceRemind> rlist = new ArrayList<>();
		Date nextMonthEnd = DateUtils.getLastDayForNextMonth(new Date(),2,2);
		log.info(DateUtils.formatDate(nextMonthEnd)+"---------保险提醒更新创建开始----------"+map.size());
		for (TbInsurance tbInsurance : remindMap.values()) {
			//下两个月保险跳过
			if(tbInsurance.getCompulsoryValidTime().after(nextMonthEnd)) {
				continue;
			}
			if(!map.containsKey(tbInsurance.getId())) {
				TbInsuranceRemind remind = new TbInsuranceRemind();
				BeanUtilsCopy.copyBeanProp(remind, tbInsurance);
				remind.setInsuranceId(tbInsurance.getId());
				rlist.add(remind);
			}
		}
		saveBatch(rlist);
		log.info(DateUtils.formatDate(nextMonthEnd)+"---------保险提醒更新创建结束----------"+rlist.size());
	}


	//获取最新保险
	public Map<String, TbInsurance> getInsurance() {
		Map<String,TbInsurance> remindMap = new HashMap<>();
		LambdaQueryWrapper<TbInsurance> queryWrapper = new LambdaQueryWrapper<>();
		//queryWrapper.lt(TbInsurance::getCompulsoryValidTime, nextMonthEnd);
		queryWrapper.orderByAsc(TbInsurance::getCompulsoryValidTime);
		List<TbInsurance> list = tbInsuranceMapper.selectList(queryWrapper);
		for (TbInsurance tbInsurance : list) {
			remindMap.put(tbInsurance.getVehicleId(), tbInsurance);
		}
		return remindMap;
	}


	@Override
	public void updateRemind() {
		Map<String, TbInsurance> remindMap = getInsurance();
		LambdaQueryWrapper<TbInsuranceRemind> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(TbInsuranceRemind::getStatus, "1");
		List<TbInsuranceRemind> list = list(queryWrapper);
		List<TbInsuranceRemind> rlist = new ArrayList<>();
		log.info("---------保险提醒更新状态开始----------"+list.size());
		for (TbInsuranceRemind remind : list) {
			if(!remindMap.containsKey(remind.getVehicleId())) {
				continue;
			}
			TbInsurance in = remindMap.get(remind.getVehicleId());
			if(in.getCompulsoryValidTime().after(remind.getCompulsoryValidTime())) {
				remind.setStatus("0");
				//remind.setCompulsoryValidTime(in.getCompulsoryValidTime());
				rlist.add(remind);
			}
		}
		updateBatchById(rlist);
		log.info("---------保险提醒更新状态结束----------"+rlist.size());
	}

    //每天1点执行
    @Scheduled(cron = "0 0 1 * * ?")
	public void insuranceRemindTask() {
    	log.info("---------保险提醒更新开始----------");
		String key = CommonConstant.INSURANCE_REMIND_TASK_LOCK;
        String value = lock.getUniqueNum();
        int n  = 0 ;
        try {
            n = lock.getLock(key, value);
            if(n > 0){
            	createRemind();

            	updateRemind();
            	log.info("---------保险提醒更新结束----------");
            }
        }catch (Exception ex){
            log.error("保险提醒更新出错, {}", ex);
        }finally {
            //释放锁
            if(n > 0){
                lock.delLock(key, value);
            }
        }
	}

    @Scheduled(cron = "0 */11 * * * ?")
	public void updateRemindTask() {

    	log.info("---------保险提醒更新状态任务开始----------");
		String key = CommonConstant.INSURANCE_REMIND_TASK_LOCK;
        String value = lock.getUniqueNum();
        int n  = 0 ;
        try {
            n = lock.getLock(key, value);
            if(n > 0){
            	updateRemind();
            	log.info("---------保险提醒更新状态任务结束----------");
            }
        }catch (Exception ex){
            log.error("保险提醒更新状态任务出错, {}", ex);
        }finally {
            //释放锁
            if(n > 0){
                lock.delLock(key, value);
            }
        }
    }

	//逾期提醒
	@Override
	public IPage<TbInsuranceRemind> getRemindPage(TbInsuranceRemind item,IPage<TbInsuranceRemind> pageList) {
		LambdaQueryWrapper<TbInsuranceRemind> queryWrapper = QueryGenerator.initQueryWrapper(TbInsuranceRemind.class, item);
		queryWrapper.ge(item.getCompulsoryValidTimeStart()!=null,TbInsuranceRemind::getCompulsoryValidTime, item.getCompulsoryValidTimeStart());
		queryWrapper.le(item.getCompulsoryValidTimeEnd()!=null,TbInsuranceRemind::getCompulsoryValidTime, item.getCompulsoryValidTimeEnd());
		Date today = DateUtils.getToday();
		//1将逾期，2已逾期(<=今天)
	    if("1".equals(item.getIsOverTime())) {
	    	queryWrapper.gt(TbInsuranceRemind::getCompulsoryValidTime, today);
		} else if("2".equals(item.getIsOverTime())) {
			queryWrapper.le(TbInsuranceRemind::getCompulsoryValidTime, today);
		}
		queryWrapper.orderByDesc(TbInsuranceRemind::getCreateTime);
		IPage<TbInsuranceRemind> list = page(pageList,queryWrapper);

		for (TbInsuranceRemind vo : list.getRecords()) {
			Integer count1 = null;
			if(vo.getCompulsoryValidTime()!=null) {
				count1 = DateUtils.differentDays(today,vo.getCompulsoryValidTime());
			}
			if(count1!=null) {
				if(count1<=0) {
					vo.setCompulsoryOverDay(-count1+"");
				}else{
					vo.setCompulsorySurplusDay(count1+"");
				}
			}
			if(ObjectUtil.isNotEmpty(vo.getInsuranceId())){
				TbInsurance insurance = tbInsuranceMapper.selectById(vo.getInsuranceId());
				if(ObjectUtil.isNotEmpty(insurance)){
					LambdaQueryWrapper<TbInsuranceRecord> countQuery = new LambdaQueryWrapper();
					countQuery.eq(TbInsuranceRecord::getVehicleId,insurance.getVehicleId());
					countQuery.between(TbInsuranceRecord::getInsuranceDate,insurance.getCompulsoryStartTime(),insurance.getCompulsoryValidTime());

					Integer occurrenceNum = tbInsuranceRecordMapper.selectCount(countQuery);
					//出险次数
					vo.setOccurrenceNum(String.valueOf(occurrenceNum));

					Double currentPremium = insurance.getCommercialPrice()+insurance.getCompulsoryPrice()+insurance.getVehicleVesselTax();
					//本期保费
					vo.setCurrentPremium(String.valueOf(currentPremium));
				}
				// TODO: 2024/2/26 下期保费，不明确规则，默认为"";
				vo.setNextPremium("");
			}
		}

		return list;
	}

}
