package com.yiboshi.science.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.hash.Hashing;
import com.yiboshi.arch.exception.BusinessException;
import com.yiboshi.science.api.ApiHttpRequest;
import com.yiboshi.science.base.BaseServiceImpl;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.config.bean.SystemProperties;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.dao.ComPersonDAO;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import com.yiboshi.science.entity.ComPerson;
import com.yiboshi.science.param.query.ComPersonQueryVO;
import com.yiboshi.science.service.ComPersonService;
import com.yiboshi.science.service.ComSendingRecordService;
import com.yiboshi.science.service.SystemUserRoleService;
import com.yiboshi.science.service.SystemUserService;
import com.yiboshi.science.utils.RedisUtils;
import com.yiboshi.yac.model.dto.UserDTO;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.yiboshi.science.utils.StringUtil.hideAllPhoneNum;
import static com.yiboshi.science.utils.StringUtil.hideAllIdCardNum;

/**
 * 人员表 Service 实现类
 *
 * @author lkl
 * @version 2021-08-26
 */
@Service
@AllArgsConstructor
public class ComPersonServiceImpl extends BaseServiceImpl<ComPersonDAO, ComPersonQueryVO, ComPersonDTO, ComPerson> implements ComPersonService {
    @Autowired
    private ComPersonDAO comPersonDAO;

    @Autowired
    private final ApiHttpRequest apiHttpRequest;

    @Autowired
    private SystemUserService systemUserService;

    @Autowired
    private SystemUserRoleService systemUserRoleService;

    @Autowired
    private ComSendingRecordService comSendingRecordService;

    @Autowired
    private final RedisUtils redisUtils;

    private SystemProperties properties;

    @Override
    protected void setCriteriaForQuery(ComPersonQueryVO vo, QueryWrapper<ComPersonQueryVO> criteria) {
        if (Objects.nonNull(vo.getCertId())) {
            criteria.like("cert_id", vo.getCertId());
        }
        if (Objects.nonNull(vo.getCertType())) {
            criteria.eq("cert_type", vo.getCertType());
        }
        if (Objects.nonNull(vo.getPersonName())) {
            criteria.like("person_name", vo.getPersonName());
        }
        if (Objects.nonNull(vo.getSex())) {
            criteria.eq("sex", vo.getSex());
        }
        if (Objects.nonNull(vo.getBirthday())) {
            criteria.eq("birthday", vo.getBirthday());
        }
        if (Objects.nonNull(vo.getUnitId())) {
            criteria.eq("unit_id", vo.getUnitId());
        }
        if (Objects.nonNull(vo.getPersonState())) {
            criteria.eq("person_state", vo.getPersonState());
        }
        if (Objects.nonNull(vo.getDegree())) {
            criteria.eq("degree", vo.getDegree());
        }
        if (Objects.nonNull(vo.getDuty())) {
            criteria.eq("duty", vo.getDuty());
        }
        if (Objects.nonNull(vo.getTitle())) {
            criteria.eq("title", vo.getTitle());
        }
        if (Objects.nonNull(vo.getSpec())) {
            criteria.eq("spec", vo.getSpec());
        }
        if (Objects.nonNull(vo.getEmail())) {
            criteria.eq("email", vo.getEmail());
        }
        if (Objects.nonNull(vo.getMobile())) {
            criteria.eq("mobile", vo.getMobile());
        }
        if (Objects.nonNull(vo.getPhoto())) {
            criteria.eq("photo", vo.getPhoto());
        }
        if (Objects.nonNull(vo.getAddress())) {
            criteria.eq("address", vo.getAddress());
        }
        if (Objects.nonNull(vo.getWorkUnit())) {
            criteria.eq("work_unit", vo.getWorkUnit());
        }
        if (Objects.nonNull(vo.getRemark())) {
            criteria.eq("remark", vo.getRemark());
        }
        if (Objects.nonNull(vo.getUnitName())) {
            criteria.like("d.unit_name", vo.getUnitName());
        }
        if (Objects.nonNull(vo.getTreeCode())) {
            criteria.eq("d.tree_code", vo.getTreeCode());
        }
        if (Objects.nonNull(vo.getRoleId())) {
            criteria.eq("l.role_id", vo.getRoleId());
        }
        if (Objects.nonNull(vo.getAuditUnit())) {
            criteria.eq("e.audit_unit", vo.getAuditUnit());
        }
        if (Objects.nonNull(vo.getAuditResult())) {
            switch (vo.getAuditResult()) {
                case 0:
                    criteria.isNotNull("e.audit_result");
                    break;
                case 10:
                    criteria.and(qw -> qw.isNull("e.audit_result").or().eq("e.audit_result", vo.getAuditResult()));
                    break;
                default:
                    criteria.eq("e.audit_result", vo.getAuditResult());
                    break;
            }
        }
    }

    @Override
    public Pagination<ComPersonDTO> getListByPage(ComPersonQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<ComPersonQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<ComPersonDTO> dtoList = comPersonDAO.getListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    @Override
    public Pagination<ComPersonDTO> getAllListByPage(ComPersonQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<ComPersonQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<ComPersonDTO> dtoList = comPersonDAO.getAllListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    @Transactional
    public String register(ComPersonDTO dto) {
        if (!apiHttpRequest.SMSCheck(dto.getMobile(), dto.getCode()))
            throw new BusinessException("验证码错误或已过期!");
        if (systemUserService.isExist(dto.getUsername()))
            throw new BusinessException("用户已存在!");
        if (this.isCertIdExist(dto.getCertId().toLowerCase(), null))
            throw new BusinessException("证件号已注册,请检查后再试!");
        if (this.isMobileExist(dto.getMobile()))
            throw new BusinessException("该手机号已注册,请检查后再试!");
        ComPerson comPerson = new ComPerson();
        comPerson.setCertId(dto.getCertId());
        comPerson.setPersonName(dto.getPersonName());
        comPerson.setUnitId(dto.getUnitId());
        comPerson.setMobile(dto.getMobile());
        comPerson.setSex(dto.getSex());
        comPerson.setBirthday(dto.getBirthday());
        comPerson.setPersonState(CommonEnum.personState.cancel.getCode());
        comPerson.setAuditResult(1);
        String personId = this.insert(comPerson);
        //创建账户
        systemUserService.CreateUser(dto.getUsername(), dto.getPassword(), personId, CommonEnum.systemRole.personal.getCode().toString(), CommonEnum.userState.cancel.getCode());
        // 清除验证码
        redisUtils.del(dto.getMobile());
        return personId;
    }

    @Transactional
    public String audit(ComPersonDTO dto) {
        ComPerson person = this.getById(dto.getId());
        if (person == null)
            throw new BusinessException("人员不存在或已删除!");
        if (Objects.isNull(person.getAuditResult()))
            throw new BusinessException("状态不允许审核!");
        ComPerson comPerson = new ComPerson();
        comPerson.setId(dto.getId());
        comPerson.setAuditPerson(SecurityUserHolder.getPersonId());
        comPerson.setAuditContent(dto.getAuditContent());
        comPerson.setAuditDate(new Date());
        if (dto.getAuditResult().equals(10)) {
            comPerson.setAuditResult(10);
            comPerson.setPersonState(1);
            if (person.getAuditResult().equals(1)) {
                this.SMSSending(person.getMobile(), person.getPersonName(), properties.getSystemName(), "用户", "已审核通过", "请使用注册账户登录系统");
            }
        } else {
            comPerson.setAuditResult(20);
            comPerson.setPersonState(2);
            if (person.getAuditResult().equals(1)) {
                this.SMSSending(person.getMobile(), person.getPersonName(), properties.getSystemName(), "用户", "审核不通过" + "(" + dto.getAuditContent() + ")", "请联系单位处理");
            }
        }
        ComPersonDTO d = this.getPersonById(dto.getId());
        systemUserService.updateStateById(d.getUserId(), CommonEnum.userState.normal.getCode());
        return this.update(comPerson);
    }

    public ComPerson getPersonByCertId(String certId) {
        if (certId == null || certId.equals(""))
            return null;
        ComPerson comPerson = new ComPerson();
        comPerson.setCertId(certId);
        comPerson = this.getEntity(comPerson);
        if (null != comPerson)
            return comPerson;
        else
            return null;
    }

    /**
     * @param id 人员id
     * @return
     */
    public ComPersonDTO getPersonById(String id) {
        ComPersonDTO dto = comPersonDAO.getPersonById(id);
        if (dto != null && !SecurityUserHolder.getRoles().contains(CommonEnum.systemRole.sys.getCode().toString()) && !SecurityUserHolder.getRoles().contains(CommonEnum.systemRole.personal.getCode().toString())) {
            if (Objects.nonNull(dto.getCertId())) {
                dto.setCertId(hideAllIdCardNum(dto.getCertId()));
            }
            if (Objects.nonNull(dto.getMobile())) {
                dto.setMobile(hideAllPhoneNum(dto.getMobile()));
            }
        }
        return dto;
    }

    public String updatePerson(ComPersonDTO d) {
        ComPerson comPerson = this.getById(d.getId());
        if (null == comPerson)
            throw new BusinessException("人员信息不存在,请检查");
        ComPerson e = this.convert2Entity(d);
        return this.update(e);
    }

    public String updatePersonFromAdmin(ComPerson e) {
        ComPerson comPerson = this.getById(e.getId());
        if (null == comPerson)
            throw new BusinessException("人员信息不存在,请检查");
        if (e.getCertId() != null) {
            e.setCertId(e.getCertId().toLowerCase());
            if (!e.getCertId().equals(comPerson.getCertId())) {
                ComPerson p = getPersonByCertId(e.getCertId());
                if (null != p)
                    throw new BusinessException("证件号已存在,请检查");
            }
        }
        return this.update(e);
    }

    public String updateState(String id, Integer state) {
        ComPerson e = new ComPerson();
        e.setId(id);
        e.setPersonState(state);
        return this.update(e);
    }

    public void getUserFromRemoteServer() {
        UserDTO loginUser = apiHttpRequest.remoteUserInfo();
        if (null != loginUser) {
            ComPerson person = this.getPersonInfoByLongId(loginUser.getId());
            if (null == person) {
                person = new ComPerson();
                person.setLongId(loginUser.getId());
                person.setId(loginUser.getUuid());
                person.setPersonState(CommonEnum.personState.normal.getCode());
                person.setCertId(loginUser.getIdentityCard());
                person.setPersonName(loginUser.getNickName());
                person.setUnitId(loginUser.getUnitId().toString());
                person.setCreated(new Date());
                this.save(person);
            }
        }
    }

    public ComPerson getPersonInfoByLongId(Long id) {
        ComPerson person = new ComPerson();
        person.setLongId(id);
        return this.getEntity(person);
    }

    public Boolean isCertIdExist(String value, String id) {
        Boolean state = false;
        ComPerson comPerson = getPersonByCertId(value);
        if (null != comPerson) {
            if (Objects.nonNull(id) && !id.equals("")) {
                ComPerson person = this.getById(id);
                if (null != person && !comPerson.getId().equals(person.getId()))
                    state = true;
            } else {
                state = true;
            }
        }
        return state;
    }

    public Boolean isMobileExist(String value) {
        Boolean state = false;
        ComPerson comPerson = new ComPerson();
        comPerson.setMobile(value);
        comPerson = this.getEntity(comPerson);
        if (null != comPerson)
            state = true;
        return state;
    }

    public boolean isComplete(ComPerson person) {
        if (null == person)
            return false;
        if (StringUtils.isEmpty(person.getPersonName()) ||
                StringUtils.isEmpty(person.getNation()) ||
                StringUtils.isEmpty(person.getTitle()) ||
                StringUtils.isEmpty(person.getSpec()) ||
                StringUtils.isEmpty(person.getDegree()) ||
                StringUtils.isEmpty(person.getDuty()) ||
                StringUtils.isEmpty(person.getEmail())) {
            return false;
        }
        return true;
    }

    public List<ComPersonDTO> getManagerListByUnitId(String unitId) {
        List<ComPersonDTO> list = comPersonDAO.getManagerListByUnitId(unitId);
        if (null != list && !SecurityUserHolder.getRoles().contains(CommonEnum.systemRole.sys.getCode().toString())) {
            list.forEach((e) -> {
                e.setCertId(hideAllIdCardNum(e.getCertId()));
                //e.setMobile(hideAllPhoneNum(e.getMobile()));
                e.setPassword(null);
            });
        }
        return list;
    }

    private void SMSSending(String mobile, String name, String systemName, String userType, String result, String message) {
        SMSSend(mobile, name, systemName, userType, result, message, apiHttpRequest, 2);
    }

    private void SMSSend(String mobile, String name, String systemName, String userType, String result, String message, ApiHttpRequest apiHttpRequest, Integer sendType) {
        long time = System.currentTimeMillis();
        String sign = Hashing.sha256().hashString(mobile + time, StandardCharsets.UTF_8).toString();
        SMSParameterDTO sms = new SMSParameterDTO();
        sms.setMobile(mobile);
        sms.setAppId(4);
        sms.setTTypeId(71);
        sms.setSmsType(2);
        sms.setCode(null);
        sms.setTimestamp(time);
        sms.setSign(sign);
        SMSTemplateDTO smsTmp = new SMSTemplateDTO();
        smsTmp.setName(name);
        smsTmp.setSystemName(systemName);
        smsTmp.setUserType(userType);
        smsTmp.setResult(result);
        smsTmp.setMessage(message);
        sms.setParamMap(smsTmp);
        if (apiHttpRequest.SMSSending(sms))
            comSendingRecordService.record(mobile, 1, sendType);
        else
            comSendingRecordService.record(mobile, 2, sendType);
    }

    public DataStatisticsDTO getRegisterPersonCount(ComPersonQueryVO v) {
        QueryWrapper criteria = new QueryWrapper();
        this.setCriteriaForQuery(v, criteria);
        return comPersonDAO.getRegisterPersonCount(criteria);
    }

    public DataStatisticsDTO getRegisterPersonCountByDay(ComPersonQueryVO v) {
        QueryWrapper criteria = new QueryWrapper();
        this.setCriteriaForQuery(v, criteria);
        return comPersonDAO.getRegisterPersonCountByDay(criteria);
    }

    @Transactional
    public List<UserImportDTO> userImport(List<UserImportDTO> list) throws IOException {
//        //职称
//        List<SystemParameter> titleList = systemParameterService.getListByType(7);
//        //专业学科
//        List<SystemParameter> specList = systemParameterService.getListByType(57);
//        for (UserImportDTO e : list) {
//            String error = "";
//            if (Objects.isNull(e.getPersonName()) || e.getPersonName().equals("")) {
//                error = error + ";姓名为空";
//            }
//            if (Objects.isNull(e.getUsername()) || e.getUsername().equals("")) {
//                error = error + ";用户名为空";
//            } else {
//                if (systemUserService.isExist(e.getUsername()))
//                    error = error + ";用户已存在";
//            }
//            if (Objects.nonNull(error) && !error.equals("")) {
//                e.setRemark(error);
//                e.setImportState("失败");
//                continue;
//            }
//            try {
//                ComUnit unit = null;
//                if (Objects.nonNull(e.getUnitName()) && !e.getUnitName().equals("")) {
//                    unit = comUnitService.isExist(e.getUnitName());
//                    if (null == unit) {
//                        unit = new ComUnit();
//                        unit.setUnitName(e.getUnitName());
//                        unit.setTreeCode(comUnitService.getNewCode("00052"));
//                        unit.setUnitState(CommonEnum.unitState.normal.getCode());
//                        unit.setRemark("导入");
//                        comUnitService.insert(unit);
//                    }
//                }
//                ComPerson comPerson = null;
//                if (Objects.nonNull(e.getCertId()) && !e.getCertId().equals("")) {
//                    comPerson = comPersonService.getPersonByCertId(e.getCertId());
//                }
//                if (null == comPerson) {
//                    comPerson = new ComPerson();
//                    comPerson.setPersonName(e.getPersonName());
//                    if (Objects.isNull(e.getCertId()) || e.getCertId().equals(""))
//                        comPerson.setCertId(String.valueOf(UUID.randomUUID()));
//                    else
//                        comPerson.setCertId(e.getCertId());
//                    comPerson.setBirthday(e.getBirthday());
//                    comPerson.setSex(e.getSex());
//                    comPerson.setMobile(e.getMobile());
//                    comPerson.setUnitId(unit != null ? unit.getId() : null);
//                    if (null != e.getSpecName() && !e.getSpecName().equals("")) {
//                        List<SystemParameter> findList2 = specList.stream().filter(p -> e.getSpecName().equals(p.getName())).collect(Collectors.toList());
//                        if (findList2.size() > 0)
//                            comPerson.setSpec(findList2.stream().findFirst().get().getId());
//                    }
//                    if (null != e.getTitleName() && !e.getTitleName().equals("")) {
//                        List<SystemParameter> findList2 = specList.stream().filter(p -> e.getTitleName().equals(p.getName())).collect(Collectors.toList());
//                        if (findList2.size() > 0)
//                            comPerson.setTitle(findList2.stream().findFirst().get().getId());
//                    }
//                    comPerson.setRemark("导入");
//                    comPerson.setPersonState(e.getState());
//                    comPersonService.insert(comPerson);
//                }
//                String personId = comPerson.getId();
//                switch (e.getRoles()) {
//                    case "1":
//                    case "2":
//                        ComManager comManager = new ComManager();
//                        comManager.setPersonId(personId);
//                        comManager.setState(e.getState());
//                        comManager.setRemark("导入");
//                        comManagerService.insert(comManager);
//                        break;
//                    case "3":
//                        ComApplicant comApplicant = new ComApplicant();
//                        comApplicant.setPersonId(personId);
//                        comApplicant.setState(e.getState());
//                        comApplicant.setRemark("导入");
//                        this.insert(comApplicant);
//                        break;
//                    case "5":
//                        ComExpert comExpert = new ComExpert();
//                        comExpert.setPersonId(personId);
//                        comExpert.setExpertState(e.getState());
//                        comExpert.setRemark("导入");
//                        comExpertService.insert(comExpert);
//                        if (Objects.nonNull(comPerson.getSpec())) {
//                            ComExpertSpec comExpertSpec = new ComExpertSpec();
//                            comExpertSpec.setExpertId(comExpert.getId());
//                            comExpertSpec.setSpecId(comPerson.getSpec());
//                            comExpertSpecService.insert(comExpertSpec);
//                        }
//                        break;
//                }
//                SystemUser systemUser = new SystemUser();
//                systemUser.setPersonId(personId);
//                systemUser.setPersonCode(e.getPersonCode());
//                systemUser.setUnit(unit != null ? unit.getId() : null);
//                systemUser.setUsername(e.getUsername());
//                systemUser.setPassword(e.getPassword());
//                systemUser.setNoteState(e.getState());
//                systemUser.setRemark("导入");
//                systemUserService.insert(systemUser);
//                e.setRemark("");
//                e.setImportState("成功");
//            } catch (Exception x) {
//                e.setRemark(x.getMessage());
//                e.setImportState("失败");
//            }
//        }
//        excelUtils.writeExcel(list);
        return list;
    }
}