package com.yizhi.application.customProject.contoller;

import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.context.TaskContext;
import com.yizhi.core.application.file.task.AbstractDefaultTask;
import com.yizhi.custom.api.feign.ExperiencePoolAuthorizeClient;
import com.yizhi.custom.api.vo.custom.ExperienceRangeImportVO;
import com.yizhi.custom.api.vo.domain.ExperiencePoolAuthorizeVo;
import com.yizhi.system.application.model.AccountNameForIdsModel;
import com.yizhi.system.application.system.remote.AccountClient;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author Ding
 * @className ExperiencePoolRangeImport
 * @description 经验池学员范围异步导入
 * @date 2018/11/7
 **/

@Component
public class ExperiencePoolRangeImport extends AbstractDefaultTask<String, Map<String, Object>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExperiencePoolRangeImport.class);

    @Autowired
    private AccountClient accountClient;

    @Autowired
    private ExperiencePoolAuthorizeClient poolAuthorizeClient;

    @Override
    protected String execute(Map<String, Object> map) {

        String ossUrl = (String) map.get("ossUrl");
        Long poolId = (Long) map.get("poolId");
        RequestContext res = (RequestContext) map.get("res");
        Long taskId = (Long) map.get("taskId");
        String serialNo = (String) map.get("serialNo");
        String taskName = (String) map.get("taskName");
        Date submitTime = new Date();

        Long accountId = res.getAccountId();
        Long companyId = res.getCompanyId();
        Long siteId = res.getSiteId();
        TaskContext taskContext = new TaskContext(taskId, serialNo, taskName, accountId, submitTime, siteId, companyId);
        working(taskContext);

        URL url = null;
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        Workbook workbook = null;
        try {
            //解析url
            String fileName = ossUrl.substring(ossUrl.lastIndexOf("/") + 1);
            String ossUrlPrefix = ossUrl.substring(0, ossUrl.lastIndexOf("/") + 1);
            ossUrl = ossUrlPrefix + URLEncoder.encode(fileName, "utf-8");

            url = new URL(ossUrl);
            connection = (HttpURLConnection) url.openConnection();
            //防止屏蔽程序抓取而返回403错误
            connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = connection.getInputStream();
            workbook = WorkbookFactory.create(inputStream);
        } catch (MalformedURLException e) {
            LOGGER.error("创建ossurl 连接错误", e);
            fail(taskContext, "创建ossurl 连接错误");
        } catch (IOException e) {
            LOGGER.error("创建ossurl 连接错误", e);
            fail(taskContext, "创建ossurl 连接错误");
        } catch (InvalidFormatException e) {
            LOGGER.error("创建Workbook 对象错误", e);
            fail(taskContext, "创建ossurl 连接错误");
        }
        try {
            if (null == workbook) {
                fail(taskContext, "创建Workbook 对象失败");
            }
            Sheet sheet = workbook.getSheetAt(0);
            Row row;
            Cell cell1 = null;//用户名
            Cell cell10 = null;//组别
            Cell cell11 = null;//批次
            Cell cell12 = null;//备注
            List<ExperienceRangeImportVO> importVOList = new ArrayList<>();
            ExperienceRangeImportVO importVO = null;
            int lastRowNum = sheet.getLastRowNum();
            List<String> names = new ArrayList<>();

            //储存用户名为空的所在行数
            List<Integer> errorList = new ArrayList<>();
            //储存不在管辖区范围的用户数据所在行数
            List<Integer> noIdList = new ArrayList<>();
            for (int i = 0; i < lastRowNum; i++) {
                String userName = null;
                String group = null;
                String batchNo = null;
                String note = null;
                importVO = new ExperienceRangeImportVO();
                row = sheet.getRow(i + 1);
                if (null != row) {
                    cell1 = row.getCell(0);
                    cell10 = row.getCell(8);
                    cell11 = row.getCell(9);
                    cell12 = row.getCell(10);
                }
                //从excel表格取值
                if (null != cell1) {
                    if (cell1.getCellTypeEnum().equals(CellType.STRING)) {
                        userName = cell1.getStringCellValue();
                    } else if (cell1.getCellTypeEnum().equals(CellType.NUMERIC)) {
                        cell1.setCellType(CellType.STRING);
                        userName = cell1.getStringCellValue();
                    }
                    if (StringUtils.isNotBlank(userName)) {
                        names.add(userName);
                        importVO.setName(userName);
                        importVO.setRowNumber(i + 2);
                        if (null != cell10) {
                            if (cell10.getCellTypeEnum().equals(CellType.STRING)) {
                                group = cell10.getStringCellValue();
                            } else if (cell10.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                cell10.setCellType(CellType.STRING);
                                group = cell10.getStringCellValue();
                            }
                            importVO.setGroup(group);
                        }
                        if (null != cell11) {
                            if (cell11.getCellTypeEnum().equals(CellType.STRING)) {
                                batchNo = cell11.getStringCellValue();
                            } else if (cell11.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                cell11.setCellType(CellType.STRING);
                                batchNo = cell11.getStringCellValue();
                            }
                            importVO.setBatchNo(batchNo);
                        }
                        if (null != cell12) {
                            if (cell12.getCellTypeEnum().equals(CellType.STRING)) {
                                note = cell12.getStringCellValue();
                            } else if (cell12.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                cell12.setCellType(CellType.STRING);
                                note = cell12.getStringCellValue();
                            }
                            importVO.setNote(note);
                        }
                        importVOList.add(importVO);
                    } else {
                        errorList.add(i + 2);
                    }
                } else {
                    errorList.add(i + 2);
                }
            }
            Map<String, Long> nameIdMap = new HashMap<>();
            //根据用户名找出对应存在的用户id
            if (CollectionUtils.isNotEmpty(names)) {
                AccountNameForIdsModel model = new AccountNameForIdsModel(names, res);
                nameIdMap = accountClient.getAccountIdByNames(model, companyId, siteId, "customProject");
            }
            List<ExperiencePoolAuthorizeVo> insertList = new ArrayList<>();
            ExperiencePoolAuthorizeVo poolAuthorize = null;
            //把用户id和对应数据装入实体并插入
            if (null != nameIdMap && nameIdMap.size() > 0) {
                for (ExperienceRangeImportVO rangeImportVO : importVOList) {
                    if (nameIdMap.containsKey(rangeImportVO.getName())) {
                        poolAuthorize = new ExperiencePoolAuthorizeVo();
                        poolAuthorize.setRelationId(nameIdMap.get(rangeImportVO.getName()));
                        poolAuthorize.setType(1);
                        poolAuthorize.setName(rangeImportVO.getName());
                        poolAuthorize.setExperienceId(poolId);
                        poolAuthorize.setBatchNo(rangeImportVO.getBatchNo());
                        poolAuthorize.setGroup(rangeImportVO.getGroup());
                        poolAuthorize.setNote(rangeImportVO.getNote());
                        poolAuthorize.setCreateById(accountId);
                        poolAuthorize.setCreateByName(res.getAccountFullName());
                        poolAuthorize.setCreateTime(new Date());
                        insertList.add(poolAuthorize);
                    } else {
                        //获取不在管辖区范围内的Name
                        noIdList.add(rangeImportVO.getRowNumber());
                    }
                }
            }else {
                for (ExperienceRangeImportVO rangeImportVO : importVOList) {
                    if (null != rangeImportVO.getName()){
                        noIdList.add(rangeImportVO.getRowNumber());
                    }
                }
            }
            boolean isOk = false;
            if (CollectionUtils.isNotEmpty(insertList)) {
                isOk = poolAuthorizeClient.insertExperiencePoolAuthorize(insertList);
            }

            errorList = (errorList == null ? new ArrayList<>() : errorList);
            noIdList = (noIdList == null ? new ArrayList<>() : noIdList);

            Integer n = insertList.size();
            success(taskContext, "成功导入" + n + "条，导入失败" + (errorList.size() + noIdList.size()) + "条", ossUrl);

            List<String> errorMsgs = new ArrayList(errorList.size());
            errorList.forEach(a -> {
                errorMsgs.add("第" + a + "行，用户名不能为空！");
            });
            noIdList.forEach(b -> {
                errorMsgs.add("第" + b + "行，管辖范围内无该用户");
            });
            //写入错误日志
            batchTaskDetail(taskId, errorMsgs);

        } catch (Exception e1) {
            fail(taskContext, "经验池可见范围过程中发生错误");
            LOGGER.error("经验池可见范围过程中发生错误", e1);
        }

        return null;
    }
}
