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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gci.boot.common.util.BeanUtilsCopy;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.common.util.JsonUtil;
import com.gci.boot.common.util.Lock;
import com.gci.boot.constant.CommonConstant;
import com.gci.boot.modules.basedata.entity.TbVehicle;
import com.gci.boot.modules.basedata.service.ITbVehicleService;
import com.gci.boot.modules.driver.entity.TbDriver;
import com.gci.boot.modules.driver.entity.TbDriverSignIn;
import com.gci.boot.modules.driver.mapper.TbDriverSignInMapper;
import com.gci.boot.modules.driver.service.ITbDriverService;
import com.gci.boot.modules.driver.service.ITbDriverSignInService;
import com.gci.boot.modules.projects.entity.Projects;
import com.gci.boot.modules.projects.service.IProjectsService;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 司机打卡 服务实现类
 * </p>
 *
 * @author xushuhan
 * @since 2023-09-13
 */
@Slf4j
@Service
public class TbDriverSignInServiceImpl extends ServiceImpl<TbDriverSignInMapper, TbDriverSignIn> implements ITbDriverSignInService {

    @Autowired
    private Lock lock;

	@Autowired
	private StringRedisTemplate redisTemplate;
	@Autowired
	private TbDriverSignInMapper driverSignInMapper;
	@Autowired
	private ITbDriverService driverService;
	@Autowired
	private IProjectsService projectsService;
    @Autowired
    private ITbVehicleService iTbVehicleService;
	
    @Scheduled(cron = "0 */5 * * * ?")
	public void signOutTask() {
    	log.info("---------司机自动签退----------");
		String key = CommonConstant.SIGN_OUT_TASK_LOCK;
        String value = lock.getUniqueNum();
        int n  = 0 ;
        try {
            n = lock.getLock(key, value);
            if(n > 0){
            	signOutTaskImpl();
            }
        }catch (Exception ex){
            log.error("司机自动签退出错, {}", ex);
        }finally {
            //释放锁
            if(n > 0){
                lock.delLock(key, value);
            }
        }
	}
	
	/**
	 * 司机自动签退
	 */
    @Override
	public void signOutTaskImpl() {
		Date today = new Date();
		today = DateUtils.addHours(today, -12);

		//获取超过12小时未签退记录
		List<TbDriverSignIn> list = lambdaQuery().eq(TbDriverSignIn::getSignInType, "1")
				.isNull(TbDriverSignIn::getSignOutId).lt(TbDriverSignIn::getSignInTime, today)
				.orderByAsc(TbDriverSignIn::getCreateTime).list();
		
		for (TbDriverSignIn last : list) {
			TbDriverSignIn sign = getNextSignIn(last);
			//如果没有签退司机，则新增数据
			if(sign==null||!"2".equals(sign.getSignInType())) {
				sign = new TbDriverSignIn();
				BeanUtilsCopy.copyBeanPropFilterId(sign, last);
				sign.setOpType("2");
				sign.setSignInType("2");
				today = DateUtils.addHours(last.getSignInTime(), 12);
				sign.setSignInTime(today);
				sign.setSysOrgCode(last.getSysOrgCode());
				sign.setCreateBy(last.getCreateBy());
				this.save(sign);
			}
			last.setSignOutId(sign.getId());
			this.updateById(last);
		}
	}
    
	public TbDriverSignIn getNextSignIn(TbDriverSignIn last) {
		Date today = DateUtils.addHours(last.getSignInTime(), 13);
		List<TbDriverSignIn> list = lambdaQuery().eq(TbDriverSignIn::getDriverId, last.getDriverId())
				.eq(TbDriverSignIn::getVehicleId, last.getVehicleId())
				.gt(TbDriverSignIn::getSignInTime, last.getSignInTime())
				.le(TbDriverSignIn::getSignInTime, today)
				.orderByAsc(TbDriverSignIn::getCreateTime).last("limit 1").list();
		return list.size()>0?list.get(0):null;
	}
    
	public TbDriverSignIn getLastSignIn(String driverId) {
		Date today = new Date();
		today = DateUtils.addHours(today, -12);
		List<TbDriverSignIn> list = lambdaQuery().eq(TbDriverSignIn::getDriverId, driverId)
				.gt(TbDriverSignIn::getSignInTime, today)
				.orderByDesc(TbDriverSignIn::getCreateTime).last("limit 1").list();
		return list.size()>0?list.get(0):null;
	}
	
	@Override
	public String sign(TbDriverSignIn sign) {
		TbDriverSignIn last = getLastSignIn(sign.getDriverId());
		if(last!=null&&"1".equals(last.getSignInType())) {
			if("1".equals(sign.getSignInType())||!sign.getVehicleId().equals(last.getVehicleId())) {
				return "请先签退车辆："+last.getPlateNumber();
			}
		}
		
		this.save(sign);
		if(last!=null&&!"1".equals(last.getSignInType())&&!StringUtils.hasLength(last.getSignOutId())) {
			last.setSignOutId(sign.getId());
			this.updateById(last);
		}
		//签到
		if("1".equals(sign.getSignInType())){
			redisTemplate.opsForValue().set(CommonConstant.VEHICLE_BIND_DRIVER+sign.getPlateNumber(), JsonUtil.object2Json(sign));
		}else{
			redisTemplate.delete(CommonConstant.VEHICLE_BIND_DRIVER+sign.getPlateNumber());
		}
		return "";
	}

	@Override
	public String queryDriverByPlateNumberAndTime(String plateNumber, String time) {
    	if(StrUtil.isBlank(plateNumber) || StrUtil.isBlank(time)){
    		return null;
		}
		return driverSignInMapper.queryDriverByPlateNumberAndTime(plateNumber,time);
	}
	
	@Override
	public void saveItemBatch(List<TbDriverSignIn> list) {
		if(list.size()<1) {
			return;
		}
		List<Projects> plist = projectsService.list();
		Map<String,String> pmap = plist.stream().collect(Collectors.toMap(Projects::getProjectName,Projects::getId));
		List<TbVehicle> vlist = iTbVehicleService.list();
		Map<String,String> vmap = vlist.stream().collect(Collectors.toMap(TbVehicle::getPlateNumber,TbVehicle::getId));
		List<TbDriver> dlist = driverService.list();
		
		List<TbDriverSignIn> items = new ArrayList<>();
		for (TbDriverSignIn tbDriverSignIn : list) {
			tbDriverSignIn.setOpType("3");
			tbDriverSignIn.setSignInDate(DateUtils.getDayStart(tbDriverSignIn.getSignInTime()));
			tbDriverSignIn.setProjectId(pmap.get(tbDriverSignIn.getProjectName()));
			tbDriverSignIn.setVehicleId(vmap.get(tbDriverSignIn.getPlateNumber()));
			String did = null;
			for (TbDriver driver : dlist) {
				if(!StringUtils.hasLength(driver.getName())||!driver.getName().equals(tbDriverSignIn.getDriverName())) {
					continue;
				}
				did = driver.getId();
				if(StringUtils.hasLength(driver.getProjectId())&&driver.getProjectId().equals(tbDriverSignIn.getProjectId())) {
					tbDriverSignIn.setDriverId(driver.getId());
					break;
				}
			}
			if(!StringUtils.hasLength(tbDriverSignIn.getDriverId())) {
				tbDriverSignIn.setDriverId(did);
			}
			if(StringUtils.hasLength(tbDriverSignIn.getDriverId())&&StringUtils.hasLength(tbDriverSignIn.getProjectId())&&
					StringUtils.hasLength(tbDriverSignIn.getVehicleId())) {
				items.add(tbDriverSignIn);
			}
		}
		saveBatch(items);
	}


}
