package com.bonus.bracelet.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.bonus.bracelet.mapper.PersonMgeMapper;
import com.bonus.bracelet.mapper.ResourceFileMapper;
import com.bonus.bracelet.service.IPersonMgeService;
import com.bonus.common.core.constant.BusinessConstants;
import com.bonus.common.core.constant.HttpStatus;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.utils.ImportExcelUtils;
import com.bonus.common.core.utils.UploadCheckUtils;
import com.bonus.common.core.utils.encryption.Sm4Utils;
import com.bonus.common.core.utils.global.SystemGlobal;
import com.bonus.common.core.utils.uuid.IdUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.entity.bracelet.BraceletParamsDto;
import com.bonus.common.entity.bracelet.exportVo.PersonExportVo;
import com.bonus.common.entity.bracelet.importVo.PersonImportVo;
import com.bonus.common.entity.bracelet.vo.BaseProject;
import com.bonus.common.entity.bracelet.vo.CertificateVo;
import com.bonus.common.entity.bracelet.vo.PersonVo;
import com.bonus.common.entity.file.ResourceFileVo;
import com.bonus.common.security.utils.ValidatorsUtils;
import com.bonus.system.api.RemoteFileService;
import com.bonus.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className:PersonMgeServiceImpl
 * @author:cwchen
 * @date:2024-07-16-11:04
 * @version:1.0
 * @description:人员-serviceImpl
 */
@Service(value = "IPersonMgeService")
@Slf4j
public class PersonMgeServiceImpl implements IPersonMgeService {

    @Resource(name = "PersonMgeMapper")
    private PersonMgeMapper mapper;

    @Resource(name = "ResourceFileMapper")
    private ResourceFileMapper resourceFileMapper;

    @Resource(name = "ValidatorsUtils")
    private ValidatorsUtils validatorsUtils;

    @Resource
    private RemoteFileService remoteFileService;

    @Value("${file.temp_file_path}")
    private String tempFilePath;

    @Override
    public List<PersonVo> getPersonLists(BraceletParamsDto dto) {
        dto.setSourceType(BusinessConstants.RESOURCE_TYPE_USER);
        List<PersonVo> list = new ArrayList<>();
        try {
            list = mapper.getPersonLists(dto);
            for (PersonVo vo : list) {
                vo = handleData(vo);
            }
        } catch (Exception e) {
            log.error("查询人员列表", e);
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addPerson(MultipartFile file, String params) {
        // 文件ID
        String delFileId = null;
        try {
            PersonVo vo = JSON.parseObject(params, PersonVo.class);
            String validResult = validatorsUtils.valid(vo, PersonVo.Query.class);
            if (StringUtils.isNotBlank(validResult)) {
                return AjaxResult.error(validResult);
            }
            // 验证身份证是否重复、手机号
            List<Map<String, String>> list = mapper.personIsExist(vo);
            if (idCardIsExist(list, vo, 1)) {
                return AjaxResult.error("身份证号码已存在");
            }
            if (idCardIsExist(list, vo, 2)) {
                return AjaxResult.error("电话已存在");
            }
            // 验证安全帽编号是否重复、马甲编号是否重复
            if(StringUtils.isNotBlank(vo.getAqmCode())){
                int result = mapper.codeIsExist(vo,1);
                if(result > 0){
                    return AjaxResult.error("安全帽编号已存在");
                }
            }
            if(StringUtils.isNotBlank(vo.getMjCode())){
                int result = mapper.codeIsExist(vo,2);
                if(result > 0){
                    return AjaxResult.error("马甲编号已存在");
                }
            }
            // 校验文件、上传文件
            String isVerify = UploadCheckUtils.uploadImgVerify(file);
            if (StringUtils.isNotBlank(isVerify)) {
                return AjaxResult.error(isVerify);
            }
            // 对身份证号、手机号 进行 sm4加密  保存人员数据、保存文件资源
            vo.setIdCard(Sm4Utils.encode(vo.getIdCard()));
            vo.setPhone(Sm4Utils.encode(vo.getPhone()));
            mapper.addPerson(vo);
            delFileId = uploadFile(file, vo);
        } catch (Exception e) {
            log.error("新增人员", e);
            // 添加失败-删除文件
            if (StringUtils.isNotEmpty(delFileId)) {
                remoteFileService.delFile(delFileId, SecurityConstants.INNER);
            }
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editPerson(MultipartFile file, String params) {
        // 文件ID
        String delFileId = null;
        try {
            PersonVo vo = JSON.parseObject(params, PersonVo.class);
            String validResult = validatorsUtils.valid(vo, PersonVo.Query.class);
            if (StringUtils.isNotBlank(validResult)) {
                return AjaxResult.error(validResult);
            }
            // 验证身份证是否重复、手机号
            List<Map<String, String>> list = mapper.personIsExist(vo);
            if (idCardIsExist(list, vo, 1)) {
                return AjaxResult.error("身份证号码已存在");
            }
            if (idCardIsExist(list, vo, 2)) {
                return AjaxResult.error("电话已存在");
            }
            // 验证安全帽编号是否重复、马甲编号是否重复
            if(StringUtils.isNotBlank(vo.getAqmCode())){
                int result = mapper.codeIsExist(vo,1);
                if(result > 0){
                    return AjaxResult.error("安全帽编号已存在");
                }
            }
            if(StringUtils.isNotBlank(vo.getMjCode())){
                int result = mapper.codeIsExist(vo,2);
                if(result > 0){
                    return AjaxResult.error("马甲编号已存在");
                }
            }
            // 校验文件、上传文件
            if (StringUtils.isNotBlank(vo.getDelFiles())) {
                String isVerify = UploadCheckUtils.uploadImgVerify(file);
                if (StringUtils.isNotBlank(isVerify)) {
                    return AjaxResult.error(isVerify);
                }
            }
            // 对身份证号、手机号 进行 sm4加密 保存人员数据 保存文件资源 删除文件
            vo.setIdCard(Sm4Utils.encode(vo.getIdCard()));
            vo.setPhone(Sm4Utils.encode(vo.getPhone()));
            mapper.editPerson(vo);
            delFileId = uploadFile(file, vo);
            if (StringUtils.isNotEmpty(vo.getDelFiles())) {
                String[] delFiles = vo.getDelFiles().split(",");
                for (String fileId : delFiles) {
                    resourceFileMapper.delResourceFile(vo.getFileId());
                    remoteFileService.delFile(fileId, SecurityConstants.INNER);
                }
            }
        } catch (Exception e) {
            log.error("修改人员", e);
            // 添加失败-删除文件
            if (StringUtils.isNotEmpty(delFileId)) {
                remoteFileService.delFile(delFileId, SecurityConstants.INNER);
            }
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult getPersonInfo(BraceletParamsDto dto) {
        try {
            dto.setSourceType(BusinessConstants.RESOURCE_TYPE_USER);
            PersonVo vo = mapper.getPersonInfo(dto);
            PersonVo handleData = handleData(vo);
            return AjaxResult.success(handleData);
        } catch (Exception e) {
            log.error("人员详情", e);
            return AjaxResult.error();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult delPerson(BraceletParamsDto dto) {
        List<CertificateVo> list = new ArrayList<>();
        try {
            if (dto.getTeamId() != null) {
                return AjaxResult.error("该人员已分配班组，请先从班组中移除该人员");
            }
            // 删除人员、资源文件、人脸照片
            mapper.delPerson(dto);
             list = mapper.getCertificate(dto);
            if(list!=null){
                for (int i = 0; i < list.size(); i++) {
                     list.get(i).setCertificateType(list.get(i).getCertificateType()+1);
                    mapper.delCertificateResourceFile(list.get(i));
                }
            }
            mapper.delCertificate(dto);
            resourceFileMapper.delResourceFile(dto.getFileId());
            remoteFileService.delFile(dto.getFilePath(), SecurityConstants.INNER);
            return AjaxResult.success();
        } catch (Exception e) {
            log.error("删除人员", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult excelUpload(MultipartFile file, HttpServletRequest request, HttpServletResponse response) {
        List<String> errorFileLists = new ArrayList<>();
        try {
            List<JSONObject> lstObj = (List<JSONObject>) ImportExcelUtils.readExcel(file, PersonExportVo.class, tempFilePath);
            List<PersonVo> list = new ArrayList<>();
            if (CollectionUtils.isEmpty(lstObj)) {
                return AjaxResult.error("请勿导入空数据");
            }
            // 校验数据是否合法、包含照片验证
            for (JSONObject obj : lstObj) {
                PersonImportVo vo = new PersonImportVo();
                PersonVo personVo = new PersonVo();
                vo = setPersonData(vo, obj);
                String isVerify = UploadCheckUtils.uploadImgVerify(vo.getFile());
                if (StringUtils.isNotBlank(isVerify)) {
                    return AjaxResult.error("第" + obj.getString("rowNo") + "行人脸照片" + isVerify);
                }
                BeanUtils.copyProperties(vo, personVo);
                String validResult = validatorsUtils.valid(personVo, PersonVo.Query.class);
                if (StringUtils.isNotBlank(validResult)) {
                    return AjaxResult.error(validResult);
                }
                list.add(personVo);
            }
            // 校验身份证号、电话是否存在相同数据
            List<String> sameList = same(list, 1, "身份证号");
            List<String> sameList2 = same(list, 2, "电话");
            String existData = isExistData(sameList);
            String existData2 = isExistData(sameList2);
            if (StringUtils.isNotBlank(existData)) {
                return AjaxResult.error(existData);
            }
            if (StringUtils.isNotBlank(existData2)) {
                return AjaxResult.error(existData2);
            }
            // 校验库中数据是否重复
            List<Map<String, String>> personIsExist = mapper.personIsExist(new PersonVo());
            for (PersonVo vo : list) {
                if (idCardIsExist(personIsExist, vo, 1)) {
                    return AjaxResult.error("第"+vo.getSerialNumber()+"行身份证号码已存在");
                }
                if (idCardIsExist(personIsExist, vo, 2)) {
                    return AjaxResult.error("第"+vo.getSerialNumber()+"行电话已存在");
                }
            }
            for (PersonVo vo : list) {
                // 对身份证号、手机号 进行 sm4加密  保存人员数据、保存文件资源
                vo.setIdCard(Sm4Utils.encode(vo.getIdCard()));
                vo.setPhone(Sm4Utils.encode(vo.getPhone()));
                mapper.addPerson(vo);
                String delFileId = uploadFile(vo.getFile(), vo);
                errorFileLists.add(delFileId);
            }
        } catch (RuntimeException runtimeException) {
            if(runtimeException.getMessage() == null){
                return AjaxResult.error("模板中含有单元格数据格式不正确");
            }
            return AjaxResult.error(runtimeException.getMessage());
        } catch (Exception e) {
            log.error(e.toString(), e);
            // 添加失败-删除文件
            if (CollectionUtils.isNotEmpty(errorFileLists)) {
                for (String delFileId : errorFileLists) {
                    remoteFileService.delFile(delFileId, SecurityConstants.INNER);
                }
            }
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    /**
     * 验证身份证号是否存在
     *
     * @param list
     * @return boolean
     * @author cwchen
     * @date 2024/7/16 13:21
     */
    public boolean idCardIsExist(List<Map<String, String>> list, PersonVo vo, int type) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        } else {
            String encodeValue = Sm4Utils.encode(type == BusinessConstants.TYPE ? vo.getIdCard() : vo.getPhone());
            for (Map<String, String> map : list) {
                String value = type == BusinessConstants.TYPE ? map.get("value") : map.get("phone");
                if (Objects.equals(encodeValue, map.get("value"))) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 文件上传
     *
     * @param file
     * @param vo
     * @return void
     * @author cwchen
     * @date 2024/7/16 14:46
     */
    public String uploadFile(MultipartFile file, PersonVo vo) {
        R result = remoteFileService.singleUploadFile(file, SecurityConstants.INNER);
        if (result != null && result.getCode() == HttpStatus.ERROR) {
            log.error("人员照片上传失败");
            return null;
        } else if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
            String jsonString = JSON.toJSONString(result.getData());
            JSONObject item = JSON.parseObject(jsonString);
            if (item != null) {
                ResourceFileVo fileVo = setResourceFileData(item, vo);
                resourceFileMapper.addFile(fileVo);
            }
            return item.getString("fileId");
        }
        return null;
    }

    public PersonVo handleData(PersonVo vo) {
        vo.setIdCard(Sm4Utils.decode(vo.getIdCard()));
        vo.setPhone(Sm4Utils.decode(vo.getPhone()));
        R<SysFile> result = remoteFileService.getImgBase64(vo.getFilePath(), SecurityConstants.INNER);
        if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
            String jsonString = JSON.toJSONString(result.getData());
            JSONObject item = JSON.parseObject(jsonString);
            String base64 = item.getString("url");
            vo.setBase64Url(base64);
        }
        return vo;
    }

    /**
     * 资源文件赋值
     *
     * @param item
     * @return ResourceFileVo
     * @author cwchen
     * @date 2024/7/16 13:49
     */
    public ResourceFileVo setResourceFileData(JSONObject item, PersonVo vo) {
        ResourceFileVo fileVo = new ResourceFileVo();
        String resourceId = IdUtils.simpleUUID();
        fileVo.setFileType(1);
        fileVo.setFilePath(item.getString("fileId"));
        fileVo.setFileSuffix(item.getString("suffix"));
        fileVo.setFileName(item.getString("fileName"));
        fileVo.setSourceId(vo.getId() + "");
        fileVo.setSourceType("1");
        return fileVo;
    }

    /**
     * 证书资源文件赋值
     * @param item
     * @param vo
     * @return
     */
    public ResourceFileVo setCertificateResourceFileData(JSONObject item, CertificateVo vo) {
        ResourceFileVo fileVo = new ResourceFileVo();
        String fileType = String.valueOf(vo.getCertificateType()+1);
        String resourceId = IdUtils.simpleUUID();
        fileVo.setFileType(vo.getCertificateType()+1);
        fileVo.setFilePath(item.getString("fileId"));
        fileVo.setFileSuffix(item.getString("suffix"));
        fileVo.setFileName(item.getString("fileName"));
        fileVo.setSourceId(vo.getId() + "");
        fileVo.setSourceType(fileType);
        return fileVo;
    }

    /**
     * 人员数据赋值
     *
     * @param vo
     * @param obj
     * @return PersonVo
     * @author cwchen
     * @date 2024/7/17 10:38
     */
    public PersonImportVo setPersonData(PersonImportVo vo, JSONObject obj) {
        vo.setSerialNumber(obj.getString("rowNum"));
        vo.setName(handleData(obj.getString("name")));
        vo.setSex(setSexData(handleData(obj.getString("sex"))));
        vo.setIdCard(handleData(obj.getString("idCard")));
        vo.setPhone(handleData(obj.getString("phone")));
        vo.setFile(obj.get("file") != null ? (MultipartFile) obj.get("file") : null);
        return vo;
    }

    /**
     * 处理性别
     *
     * @param value
     * @return Integer
     * @author cwchen
     * @date 2024/7/17 10:39
     */
    public Integer setSexData(String value) {
        switch (value) {
            case BusinessConstants.MAN:
                return 0;
            case BusinessConstants.FEMALE:
                return 1;
            case BusinessConstants.OTHER:
                return 2;
            default:
                return 3;
        }
    }

    public static List<String> same(List<PersonVo> list, int type, String name) {
        // 1 身份证号 2.手机号
        List<String> errList = new ArrayList<String>();
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < list.size(); i++) {
            String key = type == BusinessConstants.TYPE ? list.get(i).getIdCard() : list.get(i).getPhone();
            if (key == null || Objects.equals("", key)) {
                continue;
            }
            String old = map.get(key);
            if (old != null) {
                map.put(key, old + "," + (i + 3));
            } else {
                map.put(key, "" + (i + 3));
            }
        }
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = map.get(key);
            if (value.indexOf(",") != -1) {
                System.out.println(key + " 重复,行： " + value);
                errList.add(name + " 重复,重复行： " + value);
            }
        }
        return errList;
    }

    /**
     * excel表格是否存在相同数据
     *
     * @return String
     * @author cwchen
     * @date 2024/7/17 12:07
     */
    public String isExistData(List<String> sameList) {
        if (CollectionUtils.isNotEmpty(sameList)) {
            StringBuffer errStr = new StringBuffer();
            for (int j = 0; j < sameList.size(); j++) {
                errStr.append(sameList.get(j) + "\n");
            }
            return errStr.toString();
        }
        return null;
    }

    public String handleData(String value){
        if(StringUtils.isNotBlank(value)){
            return value.trim();
        }
        return null;
    }

    @Override
    public AjaxResult selectCertificateById(Integer memberId) {
        List<ResourceFileVo> highImgList = new ArrayList<>();
        List<ResourceFileVo> electricianImgList = new ArrayList<>();
        List<ResourceFileVo> elseImgList = new ArrayList<>();
        try {
           PersonVo vo = mapper.selectCertificateById(memberId);
            if(ObjectUtil.isNotEmpty(vo)){
                List<ResourceFileVo>   list = mapper.selectCertificateFile(memberId);
                getImageFile(list);
                highImgList = list.stream().filter(bracelet -> (bracelet.getSourceImagType()==2)).collect(Collectors.toList());
                electricianImgList = list.stream().filter(bracelet -> (bracelet.getSourceImagType()==3)).collect(Collectors.toList());
                elseImgList = list.stream().filter(bracelet -> (bracelet.getSourceImagType()==4)).collect(Collectors.toList());
                vo.setHighImgList(highImgList);
                vo.setElectricianImgList(electricianImgList);
                vo.setElseImgList(elseImgList);
            }
            return AjaxResult.success(vo);
        } catch (Exception e) {
            log.error("人员详情", e);
            return AjaxResult.error();
        }
    }

    /**
     * 图片查询
     * @param list
     * @return
     */
    public void  getImageFile(List<ResourceFileVo> list) {
        if(com.bonus.common.core.utils.StringUtils.isNotEmpty(list)){
            list.forEach(file->{
                R<SysFile> result = remoteFileService.getImgBase64(file.getFilePath(), SecurityConstants.INNER);
                if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
                    String jsonString = JSON.toJSONString(result.getData());
                    JSONObject item = JSON.parseObject(jsonString);
                    String base64 = item.getString("url");
                    file.setBast64Image(base64);
                }
            });
        }

    }

    public AjaxResult updateCertificate( MultipartFile[] highfile,  MultipartFile[] electfile,MultipartFile[] elsefile,  Long id){
        String delFileId = null;
        CertificateVo vo = new CertificateVo();
        try{
            if(highfile!=null) {
                R result = remoteFileService.mostUploadFile(highfile, SecurityConstants.INNER);
                if (result != null && result.getCode() == HttpStatus.ERROR) {
                    log.error("高处作业证上传失败");
                    return null;
                } else if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
                    String jsonString = JSON.toJSONString(result.getData());
                    JSONArray json = JSON.parseArray(jsonString);
                    for (int i = 0; i < json.size(); i++) {
                        JSONObject item = json.getJSONObject(i);
                        if (item != null) {
                            vo.setPeopleId(id);
                            vo.setCertificateType(1);
                            mapper.insertCertificate(vo);
                            ResourceFileVo fileVo = setCertificateResourceFileData(item, vo);
                            resourceFileMapper.addFile(fileVo);
                            delFileId = item.getString("fileId");
                        }
                    }
                }
            }
            if(electfile!=null) {
                R result2 = remoteFileService.mostUploadFile(electfile, SecurityConstants.INNER);
                if (result2 != null && result2.getCode() == HttpStatus.ERROR) {
                    log.error("电工作业证上传失败");
                    return null;
                } else if (result2 != null && result2.getCode() == HttpStatus.SUCCESS && result2.getData() != null) {
                    String jsonString = JSON.toJSONString(result2.getData());
                    JSONArray json = JSON.parseArray(jsonString);
                    for (int i = 0; i < json.size(); i++) {
                        JSONObject item = json.getJSONObject(i);
                        if (item != null) {
                            vo.setPeopleId(id);
                            vo.setCertificateType(2);
                            mapper.insertCertificate(vo);
                            ResourceFileVo fileVo = setCertificateResourceFileData(item, vo);
                            resourceFileMapper.addFile(fileVo);
                            delFileId = item.getString("fileId");
                        }
                    }
                }
            }
            if(elsefile!=null) {
                R result3 = remoteFileService.mostUploadFile(elsefile, SecurityConstants.INNER);
                if (result3 != null && result3.getCode() == HttpStatus.ERROR) {
                    log.error("其他作业证上传失败");
                    return null;
                } else if (result3 != null && result3.getCode() == HttpStatus.SUCCESS && result3.getData() != null) {
                    String jsonString = JSON.toJSONString(result3.getData());
                    JSONArray json = JSON.parseArray(jsonString);
                    for (int i = 0; i < json.size(); i++) {
                        JSONObject item = json.getJSONObject(i);
                        if (item != null) {
                            vo.setPeopleId(id);
                            vo.setCertificateType(3);
                            mapper.insertCertificate(vo);
                            ResourceFileVo fileVo = setCertificateResourceFileData(item, vo);
                            resourceFileMapper.addFile(fileVo);
                            delFileId = item.getString("fileId");
                        }
                    }
                }
            }
        }catch (Exception e) {
            log.error("新增证书", e);
            // 添加失败-删除文件
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(delFileId)) {
                remoteFileService.delFile(delFileId, SecurityConstants.INNER);
            }
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        return AjaxResult.success();

}
}
