package com.org.hktshop.service.excel;

import com.org.hktshop.Dao.Intface.IGoodsItemDao;
import com.org.hktshop.Interface.brand.IHktBrandCategoryService;
import com.org.hktshop.Interface.brand.IHktBrandService;
import com.org.hktshop.Interface.excel.HktExcelService;
import com.org.hktshop.Interface.global.IHktLanguageService;
import com.org.hktshop.Interface.product.*;
import com.org.hktshop.base.BaseResult;
import com.org.hktshop.base.BaseService;
import com.org.hktshop.base.MongoHelper;
import com.org.hktshop.entity.admin.HktAdmin;
import com.org.hktshop.entity.global.HktLanguage;
import com.org.hktshop.entity.product.*;
import com.org.hktshop.entity.vo.HktBrandInfo;
import com.org.hktshop.properties.AliyunOSSProperties;
import com.org.hktshop.utils.*;
import com.org.hktshop.utils.DateUtil;
import com.org.hktshop.utils.excel.ExcelUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.Count;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author owen
 */
@Service
public class HktExcelServiceImpl extends BaseService<HktGoods> implements HktExcelService {

    @Autowired
    IHktGoodsCategoryAttrService hktGoodsCategoryAttrService;
    @Autowired
    IHktGoodsCategoryService goodsCategoryService;
    @Autowired
    IHktBrandCategoryService hktBrandCategoryService;
    @Autowired
    IHktBrandService brandService;
    @Autowired
    IHktLanguageService languageService;
    //    @Autowired
//    IHktGoodsPriceTemplateService priceTemplateService;
    @Autowired
    IHktGoodsDeliveryService deliveryService;
    @Autowired
    IHktGoodsSeoDescService seoDescService;
    @Autowired
    IHktGoodsService goodsService;
    @Autowired
    IHktGoodsDescService goodsDescService;
    @Autowired
    IHktGoodsAttrService goodsAttrService;
    @Autowired
    private GoodsUtils goodsUtils;

    @Autowired
    private IHktGoodsCategoryService hktGoodsCategoryService;

    @Autowired
    private AliyunOSSProperties aliyunOSSProperties;
    @Autowired
    private IGoodsItemDao goodsItemDao;

    private static Logger logger = LoggerFactory.getLogger(HktExcelServiceImpl.class);

    //导入锁
    static ReentrantLock importLock = new ReentrantLock();


    /****
     * 解析商品导入
     * @return
     * @author tw
     */
    @Override
    public Ret DeCodeExcelForGoodsImport(MultipartFile file, int id, HktAdmin opUser) {

        InputStream is = null;

        StringBuffer sb = new StringBuffer();
        if (importLock.isLocked()) return Ret.create().setFail().setMsg("导入任务正在执行中,请等待数分钟...");

        importLock.lock();
        try {
            //文件为空
            if (file.isEmpty()) return Ret.create().setFail().setMsg("文件不能为空");

            long CountTime1 = System.currentTimeMillis();

            HktGoodsCategory cateQuery = new HktGoodsCategory();
            cateQuery.setId(id + "");
            HktGoodsCategory category = goodsCategoryService.queryCategory(cateQuery);
            if (category == null || category.getLevel() != 2) return Ret.create().setFail().setMsg("分类参数错误");

            //品牌
            List<HktBrandInfo> brands = brandService.queryLists(false);
            Map<String, HktBrandInfo> brandMap = new HashMap<>();
            for (HktBrandInfo info : brands) brandMap.put(info.getFno(), info);

            long CountTime2 = System.currentTimeMillis();
            logger.info("11111运行:" + (CountTime2 - CountTime1));
            //获取商品分类属性参数
            HktGoodsCategoryAttr hktGoodsCategoryAttr = new HktGoodsCategoryAttr();
            hktGoodsCategoryAttr.setCategoryId(id + "");
            List<HktGoodsCategoryAttr> categoryAttrs = hktGoodsCategoryAttrService.queryLists(hktGoodsCategoryAttr);
            //语言类型
            List<HktLanguage> languages = languageService.queryList();
            Map<String, String> languageMap = new HashMap<>();
            for (HktLanguage l : languages) languageMap.put(l.getAbbreviate(), l.getId());
            //交货周期编码
            List<HktGoodsDelivery> deliveries = deliveryService.queryLists(new HktGoodsDelivery());
            Map<String, HktGoodsDelivery> deliveryMap = new HashMap<>();
            for (HktGoodsDelivery de : deliveries) {
                deliveryMap.put(de.getFno(), de);
                deliveryMap.put(de.getLanguageId(), de);
            }
            is = file.getInputStream();
            // 由数字和26个英文字母组成的字符串
            Workbook workBook = WorkbookFactory.create(is);
            Sheet sheet = workBook.getSheetAt(0);
            Row titleRow = sheet.getRow(0);
            int cols = titleRow.getLastCellNum();
            int rows = sheet.getLastRowNum() + 1;
            long CountTime3 = System.currentTimeMillis();
            logger.info("222222运行:" + (CountTime3 - CountTime2));

            Set<String> set = new HashSet<>();
            set.add("K3物料编码");
            set.add("型号");
            set.add("品牌");
            set.add("封装");
            set.add("商品单价");
            set.add("库存数量");
            set.add("最小包装");
            set.add("常用料");
            set.add("PDF");
            //获取标题
            List<String> keyWorlds = new ArrayList<>();
            for (int i = 0; i < cols; i++) {
                Cell c = titleRow.getCell(i);
                // 判断是否具有合并单元格
                String value = ExcelUtil.getCellValue(c);
                if(set.contains(value)){
                    keyWorlds.add(value);
                }else {
                    keyWorlds.add(value+"_ch");
                }
            }
            List<String> k3ids = new ArrayList<>();
            for (int i = 1; i < rows; i++) {
                titleRow = sheet.getRow(i);
                if(titleRow == null){
                    rows--;
                    continue;
                }
                Cell c = titleRow.getCell(0);
                String value = ExcelUtil.getCellValue(c);
                if (StringUtils.isNull(value)) continue;
                if (!k3ids.contains(value)) {
                    k3ids.add(value);
                }else {
                        return   Ret.create().setFail().setMsg("ksn编码有重复");
                }
            }
            //查出商品主表内容
            List<HktGoods> goodsList = goodsService.queryByK3ids(k3ids);
            Map<String, HktGoods> goodsMap = new HashMap<>();
            k3ids.clear();
            for (HktGoods g : goodsList) {
                goodsMap.put(g.getKsn(), g);
                k3ids.add(g.getKsn());
            }
            //查出商品描述
            List<HktGoodsDesc> hktGoodsDescs = goodsDescService.queryByK3ids(k3ids);
            Map<String, List<HktGoodsDesc>> descMap = new HashMap<>();
            for (HktGoodsDesc d : hktGoodsDescs) {
                if (!descMap.containsKey(d.getGoodsId())) {
                    descMap.put(d.getGoodsId(), new ArrayList<>());
                }
                descMap.get(d.getGoodsId()).add(d);
            }
            //查出商品属性
            List<HktGoodsAttr> attrList = goodsAttrService.queryByK3ids(k3ids);
            Map<String, List<HktGoodsAttr>> goodsAttrMap = new HashMap<>();
            for (HktGoodsAttr d : attrList) {
                if (!goodsAttrMap.containsKey(d.getGoodsId())) {
                    goodsAttrMap.put(d.getGoodsId(), new ArrayList<>());
                }
                goodsAttrMap.get(d.getGoodsId()).add(d);
            }
            long CountTime4 = System.currentTimeMillis();
            logger.info("333333运行:" + (CountTime4 - CountTime3));
            List<String> sqlList = new ArrayList<>();
            for (int i = 1; i < rows; i++) {
                titleRow = sheet.getRow(i);
                if(titleRow == null){
                    break;
                }
                HktGoods goods = null;
                List<HktGoodsDesc> descs = new ArrayList<>();
                List<HktGoodsAttr> attrs = new ArrayList<>();

                String k3id = "";
                for (int j = 0; j < cols; j++) {
                    Cell c = titleRow.getCell(j);
                    String value = ExcelUtil.getCellValue(c);

                    if (StringUtils.isNull(value)) {
                        //数据未填写
                        sb.append("第" + i + "行 第" + j + "列为空");
                        continue;
                    }

                    String[] keyArr = keyWorlds.get(j).split("_");
                    String key = keyArr[0];
                    String languageId = "1";
                    HktGoodsDesc findDesc = null;
                    if (keyArr.length == 2) {
                        boolean isfind = false;
                        String add = keyArr[1];
                        if (languageMap.containsKey(add)) languageId = languageMap.get(add);
                        for (HktGoodsDesc desc : descs) {
                            if (desc.getLanguageId().equals(languageId)) {
                                findDesc = desc;
                                isfind = true;
                                break;
                            }
                        }

                        if (!isfind) {
                            findDesc = new HktGoodsDesc();
                            findDesc.setGoodsId(k3id);
                            findDesc.setLanguageId(languageId);

                            if (deliveryMap.containsKey(languageId)) {
                                //todo 设置默认发货周期
                                HktGoodsDelivery d = deliveryMap.get(languageId);
                                findDesc.setDeliveryNo(d.getFno());
                            }
                            descs.add(findDesc);
                        }
                    }

                    switch (key) {
                        case "K3物料编码":
                            k3id = value;
                            if (goodsMap.containsKey(k3id)) {
                                goods = goodsMap.get(k3id);
                                //todo 如果描述找不到是不是就会变成null，这个需要解决的问题
                                if (descMap.containsKey(k3id)) descs = descMap.get(k3id);
                                goods.setModifyTime(DateUtil.getDateTime());
//                                goods.setCategoryId(id + "");

                                if (goodsAttrMap.containsKey(k3id)) attrs = goodsAttrMap.get(k3id);
                            } else {
                                //todo 怎么把这个数据对象取出来
                                goods = new HktGoods();
                                goods.setKsn(k3id);
                                goods.setCategoryId(id + "");
                                goods.setCreateTime(DateUtil.getDateTime());
                            }
                            break;
                        case "型号":
                            goods.setMaterialSn(value);
                            break;
                        case "品牌":
                            if (brandMap.containsKey(value)) {
                                goods.setBrandId(value);
                            } else {
                                goods.setBrandId("未知");
                            }
                            break;
                        case "商品单价":
                            //System.out.println(value+"+++++++++++++++++++++++++++++++++++++");
                            goods.setPrice(Double.valueOf(value));
                            break;
                        case "库存数量":
                            goods.setStoreCount(Integer.valueOf(value));
                            break;
                        case "最小包装":
                            goods.setPackCount(Integer.valueOf(value));
                            break;
                        case "封装":
                            goods.setPackageSpecification(value);
                            break;
                        case "PDF":
                            goods.setGoodsManual("https://doc.hotking.com"+value);
                            break;
                        case "常用料":
                            //0:不常用 1:常用 2:特殊用料1 3:特殊用料...
                            switch (value){
                                case "常用料":goods.setGoodUseType(1);
                                    break;
                                case "不常用料":goods.setGoodUseType(0);
                                    break;
                                case "特殊料1":goods.setGoodUseType(2);
                                    break;
                                case "特殊料2":goods.setGoodUseType(3);
                                    break;
                                case "特殊料3":goods.setGoodUseType(4);
                                    break;
                                case "特殊料4":goods.setGoodUseType(5);
                                    break;
                                case "特殊料5":goods.setGoodUseType(6);
                                    break;
                                case "特殊料6":goods.setGoodUseType(7);
                                    break;
                                case "特殊料7":goods.setGoodUseType(8);
                                    break;
                                case "特殊料8":goods.setGoodUseType(9);
                                    break;
                                case "特殊料9":goods.setGoodUseType(10);
                                    break;
                                default: goods.setGoodUseType(11);
                                    break;
                            }
                            break;
                        case "seo关键字": {
//                            HktGoodsSeoDesc f = new HktGoodsSeoDesc();
//                            f.setName(value);
//                            f.setLanguageId(languageId);
//                            f.setUseType(2);
//                            HktGoodsSeoDesc seoDesc = seoDescService.queryDes(f);
//                            if (seoDesc == null) {
//                                seoDescService.updateDesc(opUser, f);
//                                seoDesc = seoDescService.queryDes(f);
//                            }
//                            findDesc.setKeywordsId(seoDesc.getId());
                        }
                        break;
                        case "标题":
                            findDesc.setName(value);
                            break;
                        case "工业应用":
                        case "技术应用": {
                            HktGoodsSeoDesc f = new HktGoodsSeoDesc();
                            f.setName(value);
                            f.setLanguageId(languageId);
                            f.setUseType(5);
                            HktGoodsSeoDesc seoDesc = seoDescService.queryDes(f);
                            if (seoDesc == null) {
                                seoDescService.updateDesc(opUser, f);
                                seoDesc = seoDescService.queryDes(f);
                            }
                            if ("工业应用".equals(key)) findDesc.setIndustryId(seoDesc.getId());
                            else findDesc.setTechnologyId(seoDesc.getId());
                        }
                        break;
                        case "交货周期编码":
                            if (deliveryMap.containsKey(value)) {
                                findDesc.setDeliveryNo(value);
                            }
                            break;
                       /* case "参数规格":
                            findDesc.setSpecParam(value);
                            break;*/
                        default:
                            for (HktGoodsCategoryAttr attr : categoryAttrs) {
                                if (attr.getNameCh().equals(key)) {
                                    boolean isFind = false;
                                    for (HktGoodsAttr a : attrs) {
                                        if (a.getLanguageId().equals(languageId) && a.getAttrId().equals(attr.getId())) {
                                            a.setAttrValue(value);
                                            isFind = true;
                                            a.setModifyTime(DateUtil.getDateTime());

                                            sqlList.add(ExecSqlLib.GetUpdateSql(a));
                                            break;
                                        }
                                    }
                                    if (!isFind) {
                                        HktGoodsAttr nAttr = new HktGoodsAttr();
                                        nAttr.setLanguageId(languageId);
                                        nAttr.setAttrId(attr.getId());
                                        nAttr.setCategoryId(id + "");
                                        nAttr.setAttrValue(value);
                                        nAttr.setGoodsId(k3id);
                                        nAttr.setCreateTime(DateUtil.getDateTime());

                                        sqlList.add(ExecSqlLib.GetInsertSql(nAttr));
                                    }
                                }
                            }
                            break;
                    }
                }

                if (goods == null) continue;
                //todo 这里
                for (HktGoodsDesc d : descs) {
                    if (StringUtils.isNull(d.getId()))
                        sqlList.add(ExecSqlLib.GetInsertSql(d));
                    else
                        sqlList.add(ExecSqlLib.GetUpdateSql(d));
                }
                /*try {
                    //如何商品说明数
                    String typeCode = goods.getKsn().split("\\.")[0];
                    String fileName = aliyunOSSProperties.getFileHost() + "/pdf/" + typeCode
                            + "/" + goods.getBrandId().toUpperCase().replace(".", "")
                            + "/" + goods.getMaterialSn() + ".pdf";
                    goods.setGoodsManual(fileName);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }*/
                if (StringUtils.isNull(goods.getId())) {
                    sqlList.add(ExecSqlLib.GetInsertSql(goods));
                } else {
                    sqlList.add(ExecSqlLib.GetUpdateSql(goods));
                }
            }

            long CountTime5 = System.currentTimeMillis();
            logger.info("444444运行:" + (CountTime5 - CountTime4));

            if (sqlList.size() > 0) {
                //商品分类汇总 包括所有商品
                sqlList.add("update hkt_goods_category b set  b.goods_num =  ifnull((select c.counts" +
                        "    from  (select a.category_id as id, count(a.category_id) as counts" +
                        "    from hkt_goods a group by a.category_id) c where   b.id = c.id),0)");
                //品牌数量统计
                sqlList.add("update hkt_brand b set  b.goods_num =  ifnull((select c.counts" +
                        "    from  (select a.brand_id as id, count(a.brand_id) as counts" +
                        "    from hkt_goods a  group by a.brand_id) c where   b.fno = c.id),0)");

                if (this.baseJdbcDao.executeTransaction(sqlList)) {

                    brandService.queryLists(true);
                    goodsCategoryService.InitData(true);

                    goodsAttrService.updateSelectCache(category);

                    hktGoodsCategoryService.updateCategoryForOnSell();

                    sb.append("sql执行成功");
                } else {
                    for (String sql : sqlList) {
                        System.out.println(sql + ";");
                    }
                    sb.append("sql执行失败");
                    return Ret.create().setFail().setMsg(sb.toString());
                }
            }
            long CountTime6 = System.currentTimeMillis();
            logger.info("555555运行:" + (CountTime6 - CountTime5));
        } catch (Exception ex) {
            ex.printStackTrace();
            return Ret.create().setFail().setMsg(sb.toString());
        } finally {
            importLock.unlock();
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
        }
        return Ret.create().setOk().setMsg(sb.toString());
    }

    @Override
    public HSSFWorkbook getGoodsSheet(HktGoodItem hktGoodItem) {
        String collectionName = goodsUtils.getCollectionName(hktGoodItem.getLanguage());
        MongoHelper<HktGoodItem> hktGoodItemMongoHelper = new MongoHelper<>();
        List<HktGoodItem> hktGoodItems = hktGoodItemMongoHelper.find(hktGoodItem, HktGoodItem.class, collectionName);
        HktGoodsCategoryAttr hktGoodsCategoryAttr = new HktGoodsCategoryAttr();
        hktGoodsCategoryAttr.setCategoryId(hktGoodItem.getCategoryId());
        List<HktGoodsCategoryAttr> hktGoodsCategoryAttrs = hktGoodsCategoryAttrService.queryLists(hktGoodsCategoryAttr);
        List<String> titleList;
        if("1".equals(hktGoodItem.getLanguage())){
            titleList = new ArrayList<>(Arrays.asList("K3物料编码","制造商料号", "品牌", "分类名称", "包装数量", "商品单价", "名称", "封装参数"));
            for(HktGoodsCategoryAttr hca : hktGoodsCategoryAttrs){
                titleList.add(hca.getNameCh());
            }
        }else {
            titleList = new ArrayList<>(Arrays.asList("K3物料编码","MATERIAL_SN", "BRAND", "CATEGORY", "PACKAGE", "PRICE","NAME","PACKAGESPECIFICATION"));
            for(HktGoodsCategoryAttr hca : hktGoodsCategoryAttrs){
                titleList.add(hca.getNameEn());
            }
        }
        return ExcelUtil.createWorkBook(titleList, hktGoodItems);
    }

    @Override
    public Object importExcelByPrice(MultipartFile file) {
        InputStream is = null;
        StringBuffer sb = new StringBuffer();
        if (importLock.isLocked()) return BaseResult.fail(HttpCode.BAD_REQUEST.getCode(),"导入任务正在执行中,请等待数分钟...");

        importLock.lock();
        try {
            //文件为空
            if (file.isEmpty()) return BaseResult.fail(HttpCode.BAD_REQUEST.getCode(),"文件不能为空");

            is = file.getInputStream();
            // 由数字和26个英文字母组成的字符串
            Workbook workBook = WorkbookFactory.create(is);
            Sheet sheet = workBook.getSheetAt(0);
            Row titleRow = sheet.getRow(0);
            int cols = titleRow.getLastCellNum();
            int rows = sheet.getLastRowNum() + 1;

            //获取标题
            List<String> keyWorlds = new ArrayList<>();
            for (int i = 0; i < cols; i++) {
                Cell c = titleRow.getCell(i);
                // 判断是否具有合并单元格
                String value = ExcelUtil.getCellValue(c);
                keyWorlds.add(value);
            }

            List<String> k3ids = new ArrayList<>();
            for (int i = 1; i < rows; i++) {
                titleRow = sheet.getRow(i);
                if(titleRow == null){
                    rows--;
                    continue;
                }
                Cell c = titleRow.getCell(0);
                String value = ExcelUtil.getCellValue(c);
                if (StringUtils.isNull(value)) continue;
                if (!k3ids.contains(value)) {
                    k3ids.add(value);
                }else {
                    return  BaseResult.fail(HttpCode.BAD_REQUEST.getCode(),"ksn编码有重复");
                }
            }
            //查出商品主表内容
            List<HktGoods> goodsList = goodsService.queryByK3ids(k3ids);
            Map<String, HktGoods> goodsMap = new HashMap<>();
            k3ids.clear();
            for (HktGoods g : goodsList) {
                goodsMap.put(g.getKsn(), g);
                k3ids.add(g.getKsn());
            }
            List<HktGoods> hktGoodsList = new ArrayList<>();
            List<String> sqlList = new ArrayList<>();
            for (int i = 1; i < rows; i++) {
                titleRow = sheet.getRow(i);

                HktGoods goods = null;

                String k3id = "";
                for (int j = 0; j < cols; j++) {
                    Cell c = titleRow.getCell(j);
                    String value = ExcelUtil.getCellValue(c);

                    if (StringUtils.isNull(value)) {
                        //数据未填写
                        sb.append("第" + i + "行 第" + j + "列为空");
                        continue;
                    }
                    String key = keyWorlds.get(j);
                    switch (key) {
                        case "K3物料编码":
                            k3id = value;
                            if (goodsMap.containsKey(k3id)) {
                                goods = goodsMap.get(k3id);
                                //todo 如果描述找不到是不是就会变成null，这个需要解决的问题
                                goods.setModifyTime(DateUtil.getDateTime());

                            }
                            break;
                        case "商品单价":
                            goods.setPrice(Double.valueOf(value));
                            break;
                        case "库存数量":
                            goods.setStoreCount(Integer.valueOf(value));
                            break;
                        default:
                            break;
                    }
                }

                if (goods == null) continue;
                hktGoodsList.add(goods);
                if (StringUtils.isNull(goods.getId())) {
                    sqlList.add(ExecSqlLib.GetInsertSql(goods));
                } else {
                    sqlList.add(ExecSqlLib.GetUpdateSql(goods));
                }
            }

            if (sqlList.size() > 0) {
                if (!this.baseJdbcDao.executeTransaction(sqlList)) {
                 return BaseResult.fail(HttpCode.BAD_REQUEST.getCode(),"SQL执行失败");
                }
            }
            for(HktGoods goods : hktGoodsList){
                goodsItemDao.UpdateCache(goods);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            return BaseResult.fail(HttpCode.BAD_REQUEST.getCode(),sb.toString());
        } finally {
            importLock.unlock();
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
        }
        return BaseResult.success();
    }
}
