package com.jiayue.ipfcst.console.service;

import com.jiayue.ipfcst.common.data.entity.ElectricField;
import com.jiayue.ipfcst.common.data.entity.Quartz;
import com.jiayue.ipfcst.common.data.repository.QuartzRepository;
import com.jiayue.ipfcst.common.data.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 定时逻辑
 *
 * @author bizy
 * @version 1.0
 * @since 2018/10/22 11:29
 */
@Service
@Slf4j
public class QuartzService extends BaseService {

    private final QuartzRepository quartzRepository;

    @Autowired
    public QuartzService(QuartzRepository quartzRepository) {

        this.quartzRepository = quartzRepository;

    }

    /**
     * 根据任务名查询
     *
     * @param jobName 任务名
     * @return Quartz
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Quartz findByName(String jobName) {
        return quartzRepository.findByJobName(jobName);
    }

    /**
     * 根据执行类查询
     *
     * @param executeClass 执行类
     * @return Quartz
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Quartz findByClass(
            String executeClass) {
        return quartzRepository.findByExecuteClass(executeClass);
    }

    /**
     * 保存/更新
     *
     * @param qt 任务实体
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public boolean save(Quartz qt) {
        boolean flag = false;
        try {
            flag = updateState(qt);
        } catch (Exception e) {
            log.error("系统错误", e);
        } finally {
            return flag;
        }
    }

    /**
     * 删除
     *
     * @param ids id集合
     * @return boolean
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public boolean deleteById(String ids) {
        boolean flag = false;
        try {
            if (!ids.isEmpty()) {
                String[] id = ids.split(",");
                if (null != id && id.length > 0) {
                    for (String did : id) {
                        Quartz quartz = quartzRepository.findById(Integer.parseInt(did)).get();
                        deleteJob(quartz.getJobName());
                        quartzRepository.delete(quartz);
                    }
                } else {
                    Quartz quartz = quartzRepository.findById(Integer.parseInt(ids)).get();
                    deleteJob(quartz.getJobName());
                    quartzRepository.delete(quartz);

                }
                flag = true;
            }
        } catch (Exception e) {
            log.error("系统错误", e);
        } finally {
            return flag;
        }
    }

    /**
     * 根据条件查询定时任务
     *
     * @param jobName 任务名
     * @param page    页码
     * @param size    每页多少条
     * @return map
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Map<String, Object> getQuartz(
            String jobName, String jobType, Integer page, Integer size) throws SchedulerException {
        Map<String, Object> map = new HashMap<>();
        Specification<Quartz> specification = this.getDemoQuerySpecification(jobName, jobType);
        //分页信息
        Pageable pageable = PageRequest.of(page - 1, size); //页码：前端从1开始，jpa从0开始，做个转换
        Page pageUser = quartzRepository.findAll(specification, pageable);
        List<Quartz> quartzs = pageUser.getContent();// 结果集
        if (null != quartzs && quartzs.size() > 0) {
            for (Quartz quartz : quartzs) {
                quartz.setJobState(getJobStatus(quartz.getJobName()));
                quartz.setLaetFireTime(getJobPreviousFireTime(quartz.getJobName()));
            }
        }
        quartzRepository.saveAll(quartzs);
        map.put("emps", quartzs);// 结果集
        map.put("count", pageUser.getTotalElements());// 总记录数
//        if (log.isDebugEnabled()) {
//            log.debug("查询记录数：" + pageUser.getContent().size());
//            log.debug("查询结束!");
//        }
        return map;
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<Quartz> getAll() throws SchedulerException {
        List<Quartz> quartzs = quartzRepository.findAll();
        if (null != quartzs && quartzs.size() > 0) {
            for (Quartz quartz : quartzs) {
                quartz.setJobState(getJobStatus(quartz.getJobName()));
                quartz.setLaetFireTime(getJobPreviousFireTime(quartz.getJobName()));
            }
        }
        return quartzs;
    }

    /**
     * 封装样例查询条件
     *
     * @param jobName 用户名
     * @return 封装好的样例查询条件
     */
    private Specification<Quartz> getDemoQuerySpecification(final String jobName, final String jobType) {
        return (Specification<Quartz>) (root, criteriaQuery, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (!jobName.isEmpty()) {
                predicates.add(cb.like(root.get("jobName").as(String.class), "%" + jobName + "%"));
            }
            if (!jobType.isEmpty()) {
                predicates.add(cb.like(root.get("jobType").as(String.class), "%" + jobType + "%"));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean updateState(Quartz quartz) {
        boolean flag = false;
        try {

            Class c = Class.forName(quartz.getExecuteClass());
            c.newInstance();
            if (quartz.getCronExpression().indexOf(" ") != -1) {
                scheduleJob(c, quartz.getJobName(), quartz.getStartTime(), quartz.getCronExpression(), null);
            } else {
                scheduleJob(c, quartz.getJobName(), quartz.getStartTime(),
                        Long.valueOf(Integer.parseInt(quartz.getCronExpression()) * 1000), null);
            }

            if (quartz.getJobState().equals("暂停")) {
                pauseJob(quartz.getJobName());
                log.debug("定时任务暂停：" + quartz.getJobName());
            }

            if (!quartz.getJobState().equals("暂停")) {
                log.debug("定时任务正常：" + quartz.getJobName());
                quartz.setJobState(getJobStatus(quartz.getJobName()));
            }
            quartzRepository.save(quartz);
            flag = true;

        } catch (Exception e) {
            log.error("系统错误" + e);
        } finally {
            return flag;
        }
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveCloud(Quartz quartz) {
        Quartz quartzOld = quartzRepository.findByJobName(quartz.getJobName());
        if (quartzOld != null) {
            quartz.setId(quartzOld.getId());
        }
        updateState(quartz);

    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveCloud(List<Quartz> quartzs) {
        List<Quartz> quartzs1 = quartzRepository.findAll();
        if(quartzs1!=null && quartzs1.size()>0){
            for (Quartz quartz : quartzs1) {
                deleteById(String.valueOf(quartz.getId()));
            }
        }

        if(quartzs!=null && quartzs.size()>0){
            for (Quartz quartz : quartzs) {
                updateState(quartz);
            }
        }
    }


  @Value("${spring.datasource.druid.username}")
  private String username;

  @Value("${spring.datasource.druid.password}")
  private String password;

  @Value("${spring.datasource.druid.driver-class-name}")
  private String driverClassName;

  @Value("${spring.datasource.druid.url}")
  private String url;


  /**
   * 定时任务恢复初始化
   */
  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public Boolean initJobClass() throws SQLException {
    Connection connection = null;

    try {
      String driverClassName = this.driverClassName;
      String url = this.url;
      String username = this.username;
      String password = this.password;

      Class.forName(driverClassName);
      connection = DriverManager.getConnection(url, username, password);

      ElectricField electricField = super.getElectricField();

      String elType = "G";

      if(electricField.getElectricFieldTypeEnum().getCode()==2){
        elType = "F";
      }

      String province = "E"+electricField.getProvinceEnum().getCode();


      ClassPathResource rc = new ClassPathResource("sql/jobload/"+province+"_JOB_"+elType+".sql");
      EncodedResource er = new EncodedResource(rc, "utf-8");
      ScriptUtils.executeSqlScript(connection, er);
      return true;
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    } finally {
      if (connection != null) {
        connection.close();
      }
    }
  }
}
