package com.pingcap.kb.integration.dao;

import com.pingcap.kb.integration.entity.JiraIssueStatus;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class JiraIssueDao {

  private final static String SQL_FIND_MAX_UPDATED = "select max(updated_at) from jira_issue_status;";
  private final static String SQL_FIND_BY_KEY = "select id, `key`, tracking, created_at, updated_at from jira_issue_status where `key` = ?";
  private final static String SQL_CREATE = "insert into jira_issue_status(`key`, tracking, updated_at, created_at) values (?, ?, ?, ?)";
  private final static String SQL_UPDATE = "update jira_issue_status set tracking = ?, updated_at = ?, created_at = ? where id = ?";
  private final JdbcTemplate jdbcTemplate;

  public JiraIssueDao(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }

  public Date findMaxUpdated() {
    return jdbcTemplate.queryForObject(SQL_FIND_MAX_UPDATED, Date.class);
  }

  @Transactional
  public JiraIssueStatus create(String key, boolean tracking, Date updatedAt, Date createdAt) {
    jdbcTemplate.update(SQL_CREATE, key, tracking, updatedAt, createdAt);
    return findByKey(key).orElseThrow();
  }

  public Optional<JiraIssueStatus> findByKey(String key) {
    List<JiraIssueStatus> list = jdbcTemplate.query(SQL_FIND_BY_KEY, JiraIssueStatus.ROW_MAPPER, key);
    if (list.size() == 1) {
      return Optional.of(list.get(0));
    } else if (list.isEmpty()) {
      return Optional.empty();
    } else {
      throw new DataAccessResourceFailureException("multiple results");
    }
  }

  @Transactional
  public JiraIssueStatus update(JiraIssueStatus jis) {
    jdbcTemplate.update(SQL_UPDATE, jis.isTracking(), jis.getUpdatedAt(), jis.getCreatedAt(), jis.getId());
    return findByKey(jis.getKey()).orElseThrow();
  }
}
