package com.yizhi.application.point.controller;

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.point.application.feign.PointDetailsFeignClients;
import com.yizhi.point.application.vo.PointImportVO;
import com.yizhi.system.application.model.AccountNameForIdsModel;
import com.yizhi.system.application.system.remote.AccountClient;
import org.apache.commons.collections.CollectionUtils;
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 ExternalPointImport
 * @description TODO
 * @date 2019/03/28
 **/
@Component
public class ExternalPointImport extends AbstractDefaultTask<String, Map<String, Object>> {

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

    @Autowired
    private AccountClient accountClient;

    @Autowired
    private PointDetailsFeignClients pointDetailsFeignClients;

    @Override
    protected String execute(Map<String, Object> map) {
        Long taskId = (Long) map.get("taskId");
        String serialNo = (String) map.get("serialNo");
        String taskName = (String) map.get("taskName");
        String ossUrl = (String) map.get("url");
        URL url = null;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        Workbook book = null;

        RequestContext res = (RequestContext) map.get("res");
        Long accountId = res.getAccountId();
        Long companyId = res.getCompanyId();
        Long siteId = res.getSiteId();
        Long orgId = res.getOrgId();
        String accountName = res.getAccountName();
        Date submitTime = new Date();
        TaskContext taskContext = new TaskContext(taskId, serialNo, taskName, accountId, submitTime, siteId, companyId);
        working(taskContext);
        List<PointImportVO> rowVOS = new ArrayList<>();
        PointImportVO rowVO = null;
        List<String> names = new ArrayList<>();
        List<Integer> errorList = new ArrayList<>();
        List<Integer> noIdList = new ArrayList<>();
        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);
            conn = (HttpURLConnection) url.openConnection();
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            inputStream = conn.getInputStream();
            book = 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 == book) {
                fail(taskContext, "创建Workbook 对象失败");
            }
            Sheet sheet = book.getSheetAt(0);
            Row row;
            Cell cell0;
            Cell cell1;
            Cell cell2;
            Cell cell3;
            int lastRowNum = sheet.getLastRowNum();
            //获取每行值
            if (lastRowNum > 0) {
                for (int i = 0; i < lastRowNum; i++) {
                    String name = null;
                    String fullName = null;
                    Integer point = null;
                    String description = null;

                    row = sheet.getRow(i + 1);
                    if (null != row) {
                        cell0 = row.getCell(0);
                        cell1 = row.getCell(1);
                        cell2 = row.getCell(2);
                        cell3 = row.getCell(3);
                        if (null != cell0) {
                            if (cell0.getCellTypeEnum().equals(CellType.STRING)) {
                                name = cell0.getStringCellValue();
                            } else if (cell0.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                name = String.valueOf(cell0.getNumericCellValue());
                            }
                        }
                        if (null != cell1) {
                            if (cell1.getCellTypeEnum().equals(CellType.STRING)) {
                                fullName = cell1.getStringCellValue();
                            } else if (cell1.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                fullName = String.valueOf(cell1.getNumericCellValue());
                            }
                        }
                        try {
                            if (null != cell2) {
                                if (cell2.getCellTypeEnum().equals(CellType.STRING)) {
                                    point = Integer.valueOf(cell2.getStringCellValue());
                                } else if (cell2.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                    point = (int) cell2.getNumericCellValue();
                                }
                            }
                        } catch (NumberFormatException e2) {
                            int n = i + 2;
                            LOGGER.error("第" + n + "行积分值必须是数字格式", e2);
                            taskDetail(taskId, "第" + n + "行积分值必须是数字格式");
                            continue;
                        }
                        if (null != cell3) {
                            if (cell3.getCellTypeEnum().equals(CellType.STRING)) {
                                description = cell3.getStringCellValue();
                            } else if (cell3.getCellTypeEnum().equals(CellType.NUMERIC)) {
                                description = String.valueOf(cell3.getNumericCellValue());
                            }
                        }
                        if (null != name && null != point) {
                            rowVO = new PointImportVO();
                            rowVO.setName(name.trim());
                            rowVO.setPoint(point);
                            rowVO.setRowNumber(i + 2);
                            rowVO.setDescription(description);
                            rowVOS.add(rowVO);
                            names.add(name.trim());
                        } else {
                            errorList.add(i + 2);
                            int n = i + 2;
                            taskDetail(taskId, "第" + n + "行用户名或者积分值为空");
                        }
                    }
                }
            } else {
                success(taskContext, "执行失败,未检索到数据", ossUrl);
            }

            //通过用户名找出对应的用户id
            Map<String, Long> accountMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(names)) {
                AccountNameForIdsModel model = new AccountNameForIdsModel(names, res);
                accountMap = accountClient.getAccountIdByNames(model, companyId, siteId, "point");
            }

            List<PointImportVO> list = new ArrayList<>();
            for (PointImportVO sheetRowVO : rowVOS) {
                if (null != accountMap && accountMap.size() > 0 && accountMap.containsKey(sheetRowVO.getName())) {
                    sheetRowVO.setAccountId(accountMap.get(sheetRowVO.getName()));
                    list.add(sheetRowVO);
                } else {
                    noIdList.add(sheetRowVO.getRowNumber());
                    int n = sheetRowVO.getRowNumber();
                    taskDetail(taskId, "第" + n + "行用户名不存在");
                }
            }

            if (CollectionUtils.isEmpty(errorList) && (CollectionUtils.isEmpty(noIdList))) {
                //将对应用户id和积分信息传入后台
                boolean isOk = false;
                if (CollectionUtils.isNotEmpty(list)) {
                    if (list.size() > 100) {
                        int n = list.size() / 100;
                        for (int i = 0; i < n; i++) {
                            isOk = pointDetailsFeignClients.insertExternalPoint(list.subList(100 * i, 100 * i + 100), companyId, siteId, orgId, accountId, accountName);
                        }
                        if ((list.size() % 100) > 0) {
                            isOk = pointDetailsFeignClients.insertExternalPoint(list.subList(100 * n, list.size()), companyId, siteId, orgId, accountId, accountName);
                        }
                    } else {
                        isOk = pointDetailsFeignClients.insertExternalPoint(list, companyId, siteId, orgId, accountId, accountName);
                    }
                    if (isOk) {
                        success(taskContext, "成功导入" + list.size() + "条数据", ossUrl);
                    } else {
                        success(taskContext, "导入失败,积分异常", ossUrl);
                    }
                } else {
                    success(taskContext, "执行失败,未检索到数据", ossUrl);
                }
            } else {
                success(taskContext, "执行失败,请查看详情", ossUrl);
            }

//            if (isOk) {g
//                Integer n = list.size();
//                if (CollectionUtils.isNotEmpty(errorList) && (CollectionUtils.isNotEmpty(noIdList))) {
//                    success(taskContext, "成功导入" + n + "条,第" + errorList.toString() + "行导入格式有误;第" + noIdList.toString() + "行未找到相应用户", "");
//                } else if (CollectionUtils.isNotEmpty(errorList)) {
//                    success(taskContext, "成功导入" + n + "条,第" + errorList.toString() + "行导入格式有误", "");
//                } else if (CollectionUtils.isNotEmpty(noIdList)) {
//                    success(taskContext, "成功导入" + n + "条,第" + noIdList.toString() + "行未找到相应用户", "");
//                } else if (CollectionUtils.isEmpty(errorList) && CollectionUtils.isEmpty(noIdList)) {
//                    success(taskContext, "成功导入" + n + "条,失败0条", "");
//                }
//            } else {
//                if (CollectionUtils.isNotEmpty(errorList) && (CollectionUtils.isNotEmpty(noIdList))) {
//                    success(taskContext, "成功导入" + 0 + "条,第" + errorList.toString() + "行导入格式有误;第" + noIdList.toString() + "行未找到相应用户", "");
//                } else if (CollectionUtils.isNotEmpty(errorList)) {
//                    success(taskContext, "成功导入" + 0 + "条,第" + errorList.toString() + "行导入格式有误", "");
//                } else if (CollectionUtils.isNotEmpty(noIdList)) {
//                    success(taskContext, "成功导入" + 0 + "条,第" + noIdList.toString() + "行未找到相应用户", "");
//                } else if (CollectionUtils.isEmpty(errorList) && CollectionUtils.isEmpty(noIdList)) {
//                    success(taskContext, "成功导入0条,未检索到相关数据 ", "");
//                }
//            }
        } catch (Exception e1) {
            LOGGER.error("积分导入过程出现错误:", e1);
            fail(taskContext, "积分导入过程出现错误");
        }
        return "ok";
    }
}
