package com.infoepoch.pms.dispatchassistant.infractructure.basic.user;

import com.infoepoch.pms.dispatchassistant.common.enums.EnumUtils;
import com.infoepoch.pms.dispatchassistant.common.utils.DatabaseUtils;
import com.infoepoch.pms.dispatchassistant.common.utils.OracleUtils;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.IUserQueryRepository;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.User;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.UserCriteria;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.UserType;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Repository;

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

@Repository
public class UserQueryRepository implements IUserQueryRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public List<User> selectByCriteria(UserCriteria criteria) {
        StringBuffer sql = new StringBuffer("SELECT A.*,B.UOR_ORGANIZATION_ID,C.BO_NAME FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID LEFT JOIN BAS_ORGANIZATION C ON UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), "U_DISPLAY_ORDER", false);
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql.toString(), paramList.toArray());
        List<User> userList = new ArrayList<>();
        while (sqlRowSet.next())
            userList.add(convertUser(sqlRowSet));
        return userList;
    }

    @Override
    public List<User> selectByCriteriaByPage(UserCriteria criteria, int pageIndex, int pageSize) {
        StringBuffer sql = new StringBuffer("SELECT A.*,B.UOR_ORGANIZATION_ID,C.BO_NAME FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID LEFT JOIN BAS_ORGANIZATION C ON UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), pageIndex, pageSize, "U_DISPLAY_ORDER", false);
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql.toString(), paramList.toArray());
        List<User> userList = new ArrayList<>();
        while (sqlRowSet.next())
            userList.add(convertUser(sqlRowSet));
        return userList;
    }

    @Override
    public int selectCountByCriteria(UserCriteria criteria) {
        StringBuffer sql = new StringBuffer("SELECT COUNT(1) FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID LEFT JOIN BAS_ORGANIZATION C ON UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), "U_DISPLAY_ORDER", false);
        return jdbcTemplate.queryForObject(sql.toString(), paramList.toArray(), Integer.class);
    }

    /**
     * 根据条件查询用户列表（分页）
     *
     * @param criteria
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public List<User> selectProvinceByCriteriaByPage(UserCriteria criteria, int pageIndex, int pageSize) {
        StringBuffer sql = new StringBuffer("SELECT A.*,B.UOR_ORGANIZATION_ID,C.BO_NAME FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID , BAS_ORGANIZATION C\n" +
                "    where UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), pageIndex, pageSize, "U_DISPLAY_ORDER", false);
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql.toString(), paramList.toArray());
        List<User> userList = new ArrayList<>();
        while (sqlRowSet.next())
            userList.add(convertUser(sqlRowSet));
        return userList;
    }

    /**
     * 根据条件查询用户列表
     *
     * @param criteria
     * @return
     */
    @Override
    public List<User> selectProvinceByCriteria(UserCriteria criteria) {
        StringBuffer sql = new StringBuffer("SELECT A.*,B.UOR_ORGANIZATION_ID,C.BO_NAME FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID , BAS_ORGANIZATION C\n" +
                "    where UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), "U_DISPLAY_ORDER", false);
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql.toString(), paramList.toArray());
        List<User> userList = new ArrayList<>();
        while (sqlRowSet.next())
            userList.add(convertUser(sqlRowSet));
        return userList;
    }

    /**
     * 根据条件查询用户列表总数量
     *
     * @param criteria
     * @return
     */
    @Override
    public int selectProvinceCountByCriteria(UserCriteria criteria) {
        StringBuffer sql = new StringBuffer("SELECT COUNT(1) FROM BAS_USER A LEFT JOIN BAS_USER_ORGANIZATION_RELA B ON U_ID = UOR_USER_ID , BAS_ORGANIZATION C\n" +
                "    where UOR_ORGANIZATION_ID = BO_ID");
        List<Object> paramList = OracleUtils.combinationSql(sql, createUserCriteriaAndMap(criteria), "U_DISPLAY_ORDER", false);
        return jdbcTemplate.queryForObject(sql.toString(), paramList.toArray(), Integer.class);
    }

    /**
     * @param criteria
     * @return
     */
    private Map<String, Object> createUserCriteriaAndMap(UserCriteria criteria) {
        Map<String, Object> andMap = new HashMap<>();
        if (criteria.isDisabled() != null) {
            if (criteria.isDisabled()) {
                andMap.put(" U_DISABLED = 1 ", null);
            } else {
                andMap.put(" U_DISABLED = 0 ", null);
            }
        }
        if (StringUtils.isNotBlank(criteria.getUserName())) {
            andMap.put(" U_USERNAME LIKE ?", "%" + criteria.getUserName() + "%");
        }
        if (StringUtils.isNotBlank(criteria.getFullName())) {
            andMap.put(" U_FULLNAME LIKE ?", "%" + criteria.getFullName() + "%");
        }
        if (CollectionUtils.isNotEmpty(criteria.getOrganizationIds())) {
            andMap.put(OracleUtils.placeholderIn("UOR_ORGANIZATION_ID", criteria.getOrganizationIds()), criteria.getOrganizationIds());
        }
        if (CollectionUtils.isNotEmpty(criteria.getUserIds())) {
            andMap.put(OracleUtils.placeholderIn("U_ID", criteria.getUserIds()), criteria.getUserIds());
        }
        if (CollectionUtils.isNotEmpty(criteria.getJobNumbers())) {
            andMap.put(OracleUtils.placeholderIn("U_JOB_NUMBER", criteria.getJobNumbers()), criteria.getJobNumbers());
        }
        if (StringUtils.isNotEmpty(criteria.getOrganizationId())) {
            andMap.put("UOR_ORGANIZATION_ID IN (SELECT BO_ID FROM BAS_ORGANIZATION T WHERE T.BO_ID != '5241' START WITH T.BO_ID = ? CONNECT BY PRIOR T.BO_ID = T.BO_PARENT_ID)", criteria.getOrganizationId());
        }
        if (StringUtils.isNotBlank(criteria.getJobNumberContain())) {
            andMap.put(" U_JOB_NUMBER LIKE ? ", criteria.getJobNumberContain());
        }
        if (CollectionUtils.isNotEmpty(criteria.getUsernameList())) {
            andMap.put(OracleUtils.placeholderIn("U_USERNAME", criteria.getUsernameList()), criteria.getUsernameList());
        }
        if (StringUtils.isNotBlank(criteria.getRoleName())) {
            andMap.put(" U_ID IN (SELECT UR_USER_ID FROM BAS_USER_ROLE LEFT JOIN BAS_ROLE ON UR_ROLE_ID = RL_ID WHERE RL_NAME = ?) ", criteria.getRoleName());
        }
        if (StringUtils.isNotBlank(criteria.getOrganizationName())) {
            andMap.put(" UOR_ORGANIZATION_ID IN (SELECT BO_ID FROM BAS_ORGANIZATION WHERE BO_NAME LIKE ? ) ", "%" + criteria.getOrganizationName() + "%");
        }
        if (criteria.getHasLeader() != null) {
            if (!criteria.getHasLeader()) {
                if (criteria.getBranchCompanyFlag() != null && criteria.getBranchCompanyFlag()) {
                    andMap.put(" SUBSTR(U_POSITION, LENGTH(U_POSITION)-5, LENGTH(U_POSITION)) NOT IN ('JS0003','JS0005') ", null);
                } else {
                    andMap.put(" SUBSTR(U_POSITION, LENGTH(U_POSITION)-5, LENGTH(U_POSITION)) NOT IN ('JS0003','JS0005','JS0052','JS0053') ", null);
                }

            }
        }
        return andMap;
    }

    /**
     * @param sqlRowSet
     * @return
     */
    private User convertUser(SqlRowSet sqlRowSet) {
        return new User(
                sqlRowSet.getString("U_ID"),
                sqlRowSet.getString("UOR_ORGANIZATION_ID"),
                EnumUtils.getByValue(UserType.class, sqlRowSet.getInt("U_TYPE")),
                sqlRowSet.getString("U_POSITION"),
                sqlRowSet.getString("U_DISPLAY_ORDER"),
                sqlRowSet.getString("U_USERNAME"),
                sqlRowSet.getString("U_FULLNAME"),
                sqlRowSet.getString("U_SEX"),
                sqlRowSet.getString("U_MOBILE"),
                sqlRowSet.getString("U_EMAIL"),
                sqlRowSet.getBoolean("U_DISABLED"),
                DatabaseUtils.getBigField(sqlRowSet, "U_DESCRIPTION"),
                DatabaseUtils.getBigField(sqlRowSet, "U_OA_DATA"),
                DatabaseUtils.getBigField(sqlRowSet, "U_HR_DATA"),
                sqlRowSet.getString("U_JOB_NUMBER"),
                sqlRowSet.getObject("U_ORG_CONFIRM_STATUS") == null ? null : sqlRowSet.getInt("U_ORG_CONFIRM_STATUS"),
                sqlRowSet.getString("BO_NAME")
        );
    }

}
