package com.infoepoch.pms.dispatchassistant.infractructure.oa;

import com.infoepoch.pms.dispatchassistant.common.exception.ValidationException;
import com.infoepoch.pms.dispatchassistant.common.utils.OracleUtils;
import com.infoepoch.pms.dispatchassistant.domain.oa.organization.*;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * OA组织仓储实现
 */
@Repository
public class OaOrganizationRepository implements IOaOrganizationRepository {

    private static final Logger logger = LoggerFactory.getLogger(OaOrganizationRepository.class);
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增
     */
    @Override
    public boolean insert(OaOrganization entity) {
        String sql = "INSERT INTO OA_ORGANIZATION(ORG_ID, ORG_CODE, ORG_NAME, ORG_PARENT_ID, DISPLAY_ORDER, ORG_STATUS, ORG_LEVEL, LAST_UPDATE_TIME, REFERENCE2, REFERENCE3, REFERENCE4, REFERENCE5, REFERENCE6, REFERENCE7, REFERENCE8, REFERENCE9, REFERENCE10, REFERENCE11, REFERENCE12, REFERENCE13, REFERENCE14, REFERENCE15, REGIONCODE, ORG_RECORD_TIME, REFERENCE1, ORG_OA_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getOrgId(), entity.getOrgCode(), entity.getOrgName(), entity.getOrgParentId(), entity.getDisplayOrder(), entity.getOrgStatus(), entity.getOrgLevel(), entity.getLastUpdateTime(), entity.getReference2(), entity.getReference3(), entity.getReference4(), entity.getReference5(), entity.getReference6(), entity.getReference7(), entity.getReference8(), entity.getReference9(), entity.getReference10(), entity.getReference11(), entity.getReference12(), entity.getReference13(), entity.getReference14(), entity.getReference15(), entity.getRegioncode(), entity.getOrgRecordTime(), entity.getReference1(), entity.getOrgOaId());
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw new ValidationException("新增 OA组织 失败。");
        }
        return result > 0;
    }

    /**
     * 更新
     */
    @Override
    public boolean update(OaOrganization entity) {
        String sql = "UPDATE OA_ORGANIZATION SET ORG_CODE = ?, ORG_NAME = ?, ORG_PARENT_ID = ?, DISPLAY_ORDER = ?, ORG_STATUS = ?, ORG_LEVEL = ?, LAST_UPDATE_TIME = ?, REFERENCE2 = ?, REFERENCE3 = ?, REFERENCE4 = ?, REFERENCE5 = ?, REFERENCE6 = ?, REFERENCE7 = ?, REFERENCE8 = ?, REFERENCE9 = ?, REFERENCE10 = ?, REFERENCE11 = ?, REFERENCE12 = ?, REFERENCE13 = ?, REFERENCE14 = ?, REFERENCE15 = ?, REGIONCODE = ?, ORG_RECORD_TIME = ?, REFERENCE1 = ?, ORG_OA_ID = ? WHERE ORG_ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql, entity.getOrgCode(), entity.getOrgName(), entity.getOrgParentId(), entity.getDisplayOrder(), entity.getOrgStatus(), entity.getOrgLevel(), entity.getLastUpdateTime(), entity.getReference2(), entity.getReference3(), entity.getReference4(), entity.getReference5(), entity.getReference6(), entity.getReference7(), entity.getReference8(), entity.getReference9(), entity.getReference10(), entity.getReference11(), entity.getReference12(), entity.getReference13(), entity.getReference14(), entity.getReference15(), entity.getRegioncode(), entity.getOrgRecordTime(), entity.getReference1(), entity.getOrgOaId(), entity.getOrgId());
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw new ValidationException("更新 OA组织 失败。");
        }
        return result >= 0;
    }

    /**
     * 批量新增
     */
    public int[] batchInsert(List<OaOrganization> list) {
        String sql = "INSERT INTO OA_ORGANIZATION(ORG_ID, ORG_CODE, ORG_NAME, ORG_PARENT_ID, DISPLAY_ORDER, ORG_STATUS, ORG_LEVEL, LAST_UPDATE_TIME, REFERENCE2, REFERENCE3, REFERENCE4, REFERENCE5, REFERENCE6, REFERENCE7, REFERENCE8, REFERENCE9, REFERENCE10, REFERENCE11, REFERENCE12, REFERENCE13, REFERENCE14, REFERENCE15, REGIONCODE, ORG_RECORD_TIME, REFERENCE1, ORG_OA_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                OaOrganization item = list.get(i);
                ps.setString(++j, item.getOrgId());
                ps.setString(++j, item.getOrgCode());
                ps.setString(++j, item.getOrgName());
                ps.setString(++j, item.getOrgParentId());
                ps.setString(++j, item.getDisplayOrder());
                ps.setString(++j, item.getOrgStatus());
                ps.setString(++j, item.getOrgLevel());
                ps.setString(++j, item.getLastUpdateTime());
                ps.setString(++j, item.getReference2());
                ps.setString(++j, item.getReference3());
                ps.setString(++j, item.getReference4());
                ps.setString(++j, item.getReference5());
                ps.setString(++j, item.getReference6());
                ps.setString(++j, item.getReference7());
                ps.setString(++j, item.getReference8());
                ps.setString(++j, item.getReference9());
                ps.setString(++j, item.getReference10());
                ps.setString(++j, item.getReference11());
                ps.setString(++j, item.getReference12());
                ps.setString(++j, item.getReference13());
                ps.setString(++j, item.getReference14());
                ps.setString(++j, item.getReference15());
                ps.setString(++j, item.getRegioncode());
                ps.setString(++j, item.getOrgRecordTime());
                ps.setString(++j, item.getReference1());
                ps.setString(++j, item.getOrgOaId());
            }

            @Override
            public int getBatchSize() {
                return list.size();
            }
        });
        return result;
    }

    /**
     * 批量更新
     */
    public int[] batchUpdate(List<OaOrganization> list) {
        String sql = "UPDATE OA_ORGANIZATION SET ORG_CODE = ?, ORG_NAME = ?, ORG_PARENT_ID = ?, DISPLAY_ORDER = ?, ORG_STATUS = ?, ORG_LEVEL = ?, LAST_UPDATE_TIME = ?, REFERENCE2 = ?, REFERENCE3 = ?, REFERENCE4 = ?, REFERENCE5 = ?, REFERENCE6 = ?, REFERENCE7 = ?, REFERENCE8 = ?, REFERENCE9 = ?, REFERENCE10 = ?, REFERENCE11 = ?, REFERENCE12 = ?, REFERENCE13 = ?, REFERENCE14 = ?, REFERENCE15 = ?, REGIONCODE = ?, ORG_RECORD_TIME = ?, REFERENCE1 = ?, ORG_OA_ID = ? WHERE ORG_ID = ? ";
            int[] result = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                int j = 0;
                OaOrganization item = list.get(i);
                ps.setString(++j, item.getOrgCode());
                ps.setString(++j, item.getOrgName());
                ps.setString(++j, item.getOrgParentId());
                ps.setString(++j, item.getDisplayOrder());
                ps.setString(++j, item.getOrgStatus());
                ps.setString(++j, item.getOrgLevel());
                ps.setString(++j, item.getLastUpdateTime());
                ps.setString(++j, item.getReference2());
                ps.setString(++j, item.getReference3());
                ps.setString(++j, item.getReference4());
                ps.setString(++j, item.getReference5());
                ps.setString(++j, item.getReference6());
                ps.setString(++j, item.getReference7());
                ps.setString(++j, item.getReference8());
                ps.setString(++j, item.getReference9());
                ps.setString(++j, item.getReference10());
                ps.setString(++j, item.getReference11());
                ps.setString(++j, item.getReference12());
                ps.setString(++j, item.getReference13());
                ps.setString(++j, item.getReference14());
                ps.setString(++j, item.getReference15());
                ps.setString(++j, item.getRegioncode());
                ps.setString(++j, item.getOrgRecordTime());
                ps.setString(++j, item.getReference1());
                ps.setString(++j, item.getOrgOaId());
                ps.setString(++j, item.getOrgId());
            }

            @Override
            public int getBatchSize() {
                return list.size();
            }
        });
        return result;
    }

    /**
     * 删除
     */
    @Override
    public boolean delete(String id) {
        String sql = "DELETE FROM OA_ORGANIZATION WHERE ORG_ID = ?";
        int result;
        try {
            result = jdbcTemplate.update(sql, id);
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw new ValidationException("删除 OA组织 失败。");
        }
        return result > 0;
    }

    /**
     * 根据Id查询
     */
    @Override
    public OaOrganization selectById(String id) {
        String sql = "SELECT * FROM OA_ORGANIZATION WHERE ORG_ID = ? ";
        try {
            return jdbcTemplate.queryForObject(sql, new OrganizationRowMapper(), id);
        } catch (EmptyResultDataAccessException e) {
            logger.info(e.getMessage());
            return null;
        }
    }

    /**
     * 根据查询条件查询单个对象
     */
    @Override
    public OaOrganization selectOneByCriteria(OaOrganizationCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM OA_ORGANIZATION ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria), 1, 1);
        try {
            return jdbcTemplate.queryForObject(buffer.toString(), new OrganizationRowMapper(), list.toArray());
        } catch (EmptyResultDataAccessException e) {
            logger.info(e.getMessage());
            return null;
        }
    }

    /**
     * 根据查询条件查询对象集合
     */
    @Override
    public List<OaOrganization> selectByCriteria(OaOrganizationCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM OA_ORGANIZATION ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria));
        try {
            return jdbcTemplate.query(buffer.toString(), new OrganizationRowMapper(), list.toArray());
        } catch (EmptyResultDataAccessException e) {
            logger.info(e.getMessage());
            return null;
        }
    }

    /**
     * 根据查询条件分页查询对象结合
     */
    @Override
    public List<OaOrganization> selectCriteriaByPage(OaOrganizationCriteria criteria, int pageIndex, int pageSize) {
        StringBuffer buffer = new StringBuffer("SELECT * FROM OA_ORGANIZATION ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria), pageIndex, pageSize);
        try {
            return jdbcTemplate.query(buffer.toString(), new OrganizationRowMapper(), list.toArray());
        } catch (EmptyResultDataAccessException e) {
            logger.info(e.getMessage());
            return null;
        }
    }

    /**
     * 根据条件查询对象总记录数
     */
    @Override
    public int selectCountByCriteria(OaOrganizationCriteria criteria) {
        StringBuffer buffer = new StringBuffer("SELECT COUNT(*) FROM OA_ORGANIZATION ");
        List<Object> list = OracleUtils.combinationSql(buffer, createCriteriaSql(criteria));
        Integer count = jdbcTemplate.queryForObject(buffer.toString(), Integer.class, list.toArray());
        return count == null ? 0 : count ;
    }

    /**
     * RowMapper
     */
    static class OrganizationRowMapper implements RowMapper<OaOrganization> {
        @Override
        public OaOrganization mapRow(ResultSet rs, int i) throws SQLException {
            return new OaOrganization(
                    rs.getString("ORG_ID"),
                    rs.getString("ORG_CODE"),
                    rs.getString("ORG_NAME"),
                    rs.getString("ORG_PARENT_ID"),
                    rs.getString("DISPLAY_ORDER"),
                    rs.getString("ORG_STATUS"),
                    rs.getString("ORG_LEVEL"),
                    rs.getString("LAST_UPDATE_TIME"),
                    rs.getString("REFERENCE2"),
                    rs.getString("REFERENCE3"),
                    rs.getString("REFERENCE4"),
                    rs.getString("REFERENCE5"),
                    rs.getString("REFERENCE6"),
                    rs.getString("REFERENCE7"),
                    rs.getString("REFERENCE8"),
                    rs.getString("REFERENCE9"),
                    rs.getString("REFERENCE10"),
                    rs.getString("REFERENCE11"),
                    rs.getString("REFERENCE12"),
                    rs.getString("REFERENCE13"),
                    rs.getString("REFERENCE14"),
                    rs.getString("REFERENCE15"),
                    rs.getString("REGIONCODE"),
                    rs.getString("ORG_RECORD_TIME"),
                    rs.getString("REFERENCE1"),
                    rs.getString("ORG_OA_ID")
            );
        }
    }

    /**
     * 创建查询条件
     */
    private Map<String, Object> createCriteriaSql(OaOrganizationCriteria criteria) {
        Map<String, Object> andMap = new LinkedHashMap<>();
        if (criteria == null)
            return andMap;
        //if (criteria.byId())
        //    andMap.put(criteria.getId() == null ? " T_Id IS NULL " : " T_Id = ? ", criteria.getId());

        //
        if (criteria.byOrgId())
            andMap.put(criteria.getOrgId() == null ? " ORG_ID IS NULL " : " ORG_ID = ? ", criteria.getOrgId());
        //
        if (criteria.byOrgCode())
            andMap.put(criteria.getOrgCode() == null ? " ORG_CODE IS NULL " : " ORG_CODE = ? ", criteria.getOrgCode());
        //
        if (criteria.byOrgName())
            andMap.put(criteria.getOrgName() == null ? " ORG_NAME IS NULL " : " ORG_NAME = ? ", criteria.getOrgName());
        //（LIKE）
        if (criteria.byOrgNameContain())
            andMap.put(" ORG_NAME LIKE ? ", "%" + criteria.getOrgNameContain() + "%");
        //
        if (criteria.byOrgParentId())
            andMap.put(criteria.getOrgParentId() == null ? " ORG_PARENT_ID IS NULL " : " ORG_PARENT_ID = ? ", criteria.getOrgParentId());
        //
        if (criteria.byOrgStatus())
            andMap.put(criteria.getOrgStatus() == null ? " ORG_STATUS IS NULL " : " ORG_STATUS = ? ", criteria.getOrgStatus());
        //
        if (criteria.byOrgLevel())
            andMap.put(criteria.getOrgLevel() == null ? " ORG_LEVEL IS NULL " : " ORG_LEVEL = ? ", criteria.getOrgLevel());
        //
        if (criteria.byLastUpdateTime())
            andMap.put(criteria.getLastUpdateTime() == null ? " LAST_UPDATE_TIME IS NULL " : " LAST_UPDATE_TIME = ? ", criteria.getLastUpdateTime());
        //
        if (criteria.byOrgRecordTime())
            andMap.put(criteria.getOrgRecordTime() == null ? " ORG_RECORD_TIME IS NULL " : " ORG_RECORD_TIME = ? ", criteria.getOrgRecordTime());
        //
        if (criteria.byOrgOaId())
            andMap.put(criteria.getOrgOaId() == null ? " ORG_OA_ID IS NULL " : " ORG_OA_ID = ? ", criteria.getOrgOaId());

        if(CollectionUtils.isNotEmpty(criteria.getOrgCodeList())) {
            andMap.put(OracleUtils.placeholderIn("ORG_CODE", criteria.getOrgCodeList()), criteria.getOrgCodeList());
        }
        return andMap;
    }

}
