package com.zbf.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbf.common.annotation.Log;
import com.zbf.common.core.domain.AjaxResult;
import com.zbf.common.exception.ServiceException;
import com.zbf.common.utils.bean.BeanValidators;
import com.zbf.system.domain.TBaseGoods;
import com.zbf.system.domain.TCkPickingwavegoods;
import com.zbf.system.domain.TMiStock;
import com.zbf.system.domain.TOngoodsshelf;
import com.zbf.system.mapper.TBaseGoodsMapper;
import com.zbf.system.mapper.TCkPickingwavegoodsMapper;
import com.zbf.system.mapper.TMiStockMapper;
import com.zbf.system.mapper.TOngoodsshelfMapper;
import com.zbf.system.service.ITBaseGoodsService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.validation.Validator;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * 物料Service业务层处理
 *
 * @author sunits
 * @date 2024-06-15
 */
@Service
public class TBaseGoodsServiceImpl extends ServiceImpl<TBaseGoodsMapper, TBaseGoods> implements ITBaseGoodsService //修改
{
    private static final Logger logger = LoggerFactory.getLogger(TBaseGoodsServiceImpl.class);
    @Resource
    private TBaseGoodsMapper tBaseGoodsMapper;
    @Resource
    private TMiStockMapper tMiStockMapper;
    @Resource
    private TOngoodsshelfMapper tOngoodsshelfMapper;
    @Resource
    private TCkPickingwavegoodsMapper tCkPickingwavegoodsMapper;
    @Autowired
    protected Validator validator;

    /**
     * 查询物料
     *
     * @param id 物料主键
     * @return 物料
     */
    @Override
    public TBaseGoods selectTBaseGoodsById(Long id) {
        return tBaseGoodsMapper.selectTBaseGoodsById(id);
    }

    /**
     * 查询物料列表
     *
     * @param tBaseGoods 物料
     * @return 物料
     */
    @Override
    public List<TBaseGoods> selectTBaseGoodsList(TBaseGoods tBaseGoods) {
        return tBaseGoodsMapper.selectTBaseGoodsList(tBaseGoods);
    }

    /**
     * 新增物料
     *
     * @param tBaseGoods 物料
     * @return 结果
     */
    @Override
    public int insertTBaseGoods(TBaseGoods tBaseGoods) {

        logger.info("插入物料信息开始====》》》{}", tBaseGoods);
        //查询是否已经包含了该物料
        TBaseGoods tBaseGoods1 = new TBaseGoods();
        tBaseGoods1.setGoodsId(tBaseGoods.getGoodsId());
        List<TBaseGoods> tBaseGoods2 = tBaseGoodsMapper.selectTBaseGoodsList(tBaseGoods1);
//        if(tBaseGoods2.size() > 0){
//            throw new RuntimeException("该物料已存在，请勿重复添加");
//        }
        if (tBaseGoods2.size() > 0) {
            TBaseGoods tBaseGoods3 = tBaseGoods2.get(0);


            boolean isSame = true;
            if (StringUtils.isNotBlank(tBaseGoods3.getGoodsName())) {
                if (!tBaseGoods3.getGoodsName().equals(tBaseGoods.getGoodsName())) {
                    logger.warn("物料名称不同");
                    isSame = false;
                }
            } else {
                if (StringUtils.isNotBlank(tBaseGoods3.getGoodsName())) {
                    isSame = false;
                }
            }
            if (StringUtils.isNotBlank(tBaseGoods3.getRecoil())) {
                if (!tBaseGoods3.getRecoil().equals(tBaseGoods.getRecoil())) {
                    logger.warn("图号不同");
                    isSame = false;
                }
            } else {
                if (StringUtils.isNotBlank(tBaseGoods.getRecoil())) {
                    isSame = false;
                }
            }
            if (StringUtils.isNotBlank(tBaseGoods3.getSpecification())) {
                if (!tBaseGoods3.getSpecification().equals(tBaseGoods.getSpecification())) {
                    logger.warn("规格不同");
                    isSame = false;
                }
            } else {
                if (StringUtils.isNotBlank(tBaseGoods.getSpecification())) {
                    isSame = false;
                }
            }
            if (StringUtils.isNotBlank(tBaseGoods3.getGoodsTypeId())) {
                if (!tBaseGoods3.getGoodsTypeId().equals(tBaseGoods.getGoodsTypeId())) {
                    logger.warn("类型不同");
                    isSame = false;
                }
            } else {
                if (StringUtils.isNotBlank(tBaseGoods.getGoodsTypeId())) {
                    isSame = false;
                }
            }
            if (StringUtils.isNotBlank(tBaseGoods3.getUnit())) {
                if (!tBaseGoods3.getUnit().equals(tBaseGoods.getUnit())) {
                    isSame = false;
                }
            } else {
                if (StringUtils.isNotBlank(tBaseGoods.getUnit())) {
                    isSame = false;
                }
            }
            //如果库存和出入库任务有相关物料，则更新
            if (!isSame) {
                TMiStock tMiStock = new TMiStock();
                tMiStock.setGoodsId(tBaseGoods.getGoodsId());
                QueryWrapper<TMiStock> queryWrapper = new QueryWrapper<>(tMiStock);
                List<TMiStock> tMiStocks = tMiStockMapper.selectList(queryWrapper);
                if (tMiStocks.size() > 0) {
                    for (TMiStock tMiStock1 : tMiStocks) {
                        //库存
                        TMiStock tMiStock2 = new TMiStock();
                        tMiStock2.setGoodsName(tBaseGoods.getGoodsName());
                        tMiStock2.setSpecification(tBaseGoods.getSpecification());
                        tMiStock2.setOriBill(tBaseGoods.getRecoil());
                        tMiStock2.setId(tMiStock1.getId());
                        tMiStock2.setUnit(tMiStock1.getUnit());
                        logger.info("更新库存：{}", tMiStock2);
                        tMiStockMapper.updateById(tMiStock2);
                    }
                }

                //入库任务
                TOngoodsshelf tOngoodsshelf = new TOngoodsshelf();
                tOngoodsshelf.setGoodsId(tBaseGoods.getGoodsId());
                List<TOngoodsshelf> tOngoodsshelves = tOngoodsshelfMapper.selectTOngoodsshelfList(tOngoodsshelf);
                if (tOngoodsshelves.size() > 0) {
                    for (TOngoodsshelf tOngoodsshelf1 : tOngoodsshelves) {
                        TOngoodsshelf tOngoodsshelf2 = new TOngoodsshelf();
                        tOngoodsshelf2.setGoodsName(tBaseGoods.getGoodsName());
                        tOngoodsshelf2.setRecoil(tBaseGoods.getRecoil());
                        tOngoodsshelf2.setSpecification(tBaseGoods.getSpecification());
                        tOngoodsshelf2.setId(tOngoodsshelf1.getId());
                        tOngoodsshelf2.setUnit(tBaseGoods.getUnit());
                        logger.info("更新入库任务：{}", tOngoodsshelf2);

                        tOngoodsshelfMapper.updateTOngoodsshelf(tOngoodsshelf2);
                    }
                }
                //出库任务
                TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
                tCkPickingwavegoods.setGoodsId(tBaseGoods.getGoodsId());
                List<TCkPickingwavegoods> tCkPickingwavegoodsList = tCkPickingwavegoodsMapper.selectTCkPickingwavegoodsList(tCkPickingwavegoods);
                if (tCkPickingwavegoodsList.size() > 0) {
                    for (TCkPickingwavegoods tCkPickingwavegoods1 : tCkPickingwavegoodsList) {
                        TCkPickingwavegoods tCkPickingwavegoods2 = new TCkPickingwavegoods();
                        tCkPickingwavegoods2.setGoodsName(tBaseGoods.getGoodsName());
                        tCkPickingwavegoods2.setSpecification(tBaseGoods.getSpecification());
                        tCkPickingwavegoods2.setRecoil(tBaseGoods.getRecoil());
                        tCkPickingwavegoods2.setId(tCkPickingwavegoods1.getId());
                        logger.info("更新出库任务：{}", tCkPickingwavegoods2);
                        tCkPickingwavegoodsMapper.updateTCkPickingwavegoods(tCkPickingwavegoods2);
                    }
                }
            }


            tBaseGoods3.setGoodsName(tBaseGoods.getGoodsName());
            tBaseGoods3.setUnit(tBaseGoods.getUnit());
            tBaseGoods3.setGoodsShortName(tBaseGoods.getGoodsShortName());
            tBaseGoods3.setRecoil(tBaseGoods.getRecoil());
            tBaseGoods3.setGoodsTypeId(tBaseGoods.getGoodsTypeId());
            tBaseGoods3.setSpecification(tBaseGoods.getSpecification());
            tBaseGoods3.setWarnUp(tBaseGoods.getWarnUp());
            tBaseGoods3.setWarnDown(tBaseGoods.getWarnDown());
            tBaseGoods3.setRemark(tBaseGoods.getRemark());

            tBaseGoodsMapper.updateTBaseGoods(tBaseGoods3);
            logger.info("更新物料：{}", tBaseGoods3);


        } else {
            tBaseGoodsMapper.insertTBaseGoods(tBaseGoods);
        }
        return 1;
    }

    /**
     * 修改物料
     *
     * @param tBaseGoods 物料
     * @return 结果
     */
    @Override
    public int updateTBaseGoods(TBaseGoods tBaseGoods) {
        logger.info("更改物料信息开始====》》》{}", tBaseGoods);
        return tBaseGoodsMapper.updateTBaseGoods(tBaseGoods);
    }

    /**
     * 批量删除物料
     *
     * @param ids 需要删除的物料主键
     * @return 结果
     */
    @Override
    public int deleteTBaseGoodsByIds(Long[] ids) {
        logger.info("删除物料信息开始====》》》{}", ids);
        return tBaseGoodsMapper.deleteTBaseGoodsByIds(ids);
    }

    /**
     * 删除物料信息
     *
     * @param id 物料主键
     * @return 结果
     */
    @Override
    public int deleteTBaseGoodsById(Long id) {
        logger.info("删除物料信息开始====》》》{}", id);
        return tBaseGoodsMapper.deleteTBaseGoodsById(id);
    }


    /**
     * 批量禁用
     *
     * @param ids 物料主键
     * @return 结果
     */
    @Override
    public int disabledTBaseGoodsByIds(Long[] ids) {
        return tBaseGoodsMapper.disabledTBaseGoodsByIds(ids);
    }

    /**
     * 批量启用
     *
     * @param ids 物料主键
     * @return 结果
     */
    @Override
    public int enableTBaseGoodsByIds(Long[] ids) {
        return tBaseGoodsMapper.enableTBaseGoodsByIds(ids);
    }

    /**
     * 修改状态
     *
     * @param tBaseGoods 工序管理主键
     * @return 结果
     */
    @Override
    public int updateStatus(TBaseGoods tBaseGoods) {
        return tBaseGoodsMapper.updateTBaseGoods(tBaseGoods);
    }

    /**
     * 模糊查询商品资料
     *
     * @param goodsId 商品资料主键
     * @return 商品资料
     */
    @Override
    public List<TBaseGoods> queryTBaseGoodsByGoodsId(String goodsId) {
        return tBaseGoodsMapper.queryTBaseGoodsByGoodsId(goodsId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<TBaseGoods> list, boolean updateSupport, String userName) {
        if (com.zbf.common.utils.StringUtils.isNull(list) || list.size() == 0) {
            throw new ServiceException("导入物料数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        for (TBaseGoods tBaseGoods : list) {
            try {
                // 验证是否存在这个托盘
                TBaseGoods old = tBaseGoodsMapper.selectOne(new QueryWrapper<TBaseGoods>().eq("goods_id", tBaseGoods.getGoodsId()));
                if (com.zbf.common.utils.StringUtils.isNull(old)) {
                    BeanValidators.validateWithException(validator, tBaseGoods);
                    tBaseGoodsMapper.insertTBaseGoods(tBaseGoods);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、物料 " + tBaseGoods.getGoodsId() + " 导入成功");

                    // 推送成功导入的数据
                    dataPush(Collections.singletonList(tBaseGoods)); // 推送当前成功导入的物料
                } else if (updateSupport) {
                    BeanValidators.validateWithException(validator, tBaseGoods);
                    tBaseGoodsMapper.updateTBaseGoods(tBaseGoods);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、物料 " + tBaseGoods.getGoodsId() + " 更新成功");

                    // 推送成功更新的数据
                    dataPush(Collections.singletonList(tBaseGoods)); // 推送当前成功更新的物料
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、物料 " + tBaseGoods.getGoodsId() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、物料 " + tBaseGoods.getGoodsId() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }

        return successMsg.toString();
    }

    @Override
    public int saveRfid(TBaseGoods goods) {
        String goodsId = goods.getGoodsId();
        TBaseGoods tBaseGoods = tBaseGoodsMapper.selebyGoodId(goodsId);
        if (tBaseGoods==null){
            throw new RuntimeException("暂无基础物料数据");
        }

        if (tBaseGoods.getGoodsEpc() != null && goods.getGoodsEpc() != null) {
            // 处理数据库中现有的EPC
            int existingQuantity = extractQuantityFromEpc(tBaseGoods.getGoodsEpc());
            System.out.println("现有数量: " + existingQuantity);  // 调试输出

            // 处理新传入的EPC
            int newQuantity = extractQuantityFromEpc(goods.getGoodsEpc());
            System.out.println("新传入数量: " + newQuantity);  // 调试输出

            // 数量相加
            int totalQuantity = existingQuantity + newQuantity;
            System.out.println("总数量: " + totalQuantity);  // 调试输出

            // 获取编号（S前面的部分）
            String prefix = extractPrefixFromEpc(goods.getGoodsEpc());

            // 生成新的24位十六进制EPC
            String newEpc = generateNewEpc(prefix, totalQuantity);

            // 设置新的EPC到要更新的对象中
            tBaseGoods.setGoodsTid(goods.getGoodsTid());
            tBaseGoods.setGoodsEpc(newEpc);  // 使用计算后的新EPC

            // 更新数据库
            int i = tBaseGoodsMapper.updateRFID(tBaseGoods);
            return i > 0 ? 1 : 0;
        }

        // 如果EPC为空的情况
        tBaseGoods.setGoodsTid(goods.getGoodsTid());
        tBaseGoods.setGoodsEpc(goods.getGoodsEpc());
        int i = tBaseGoodsMapper.updateRFID(tBaseGoods);
        return i > 0 ? 1 : 0;
    }

    private int extractQuantityFromEpc(String epc) {
        try {
            // 将十六进制转换为字符串
            byte[] bytes = new byte[epc.length() / 2];
            for (int i = 0; i < epc.length(); i += 2) {
                bytes[i / 2] = (byte) ((Character.digit(epc.charAt(i), 16) << 4)
                        + Character.digit(epc.charAt(i + 1), 16));
            }
            String result = new String(bytes, StandardCharsets.UTF_8);
            System.out.println("转换后的字符串: " + result);  // 调试输出

            // 提取SS之间的数量
            int firstS = result.indexOf('S');
            int secondS = result.indexOf('S', firstS + 1);

            if (firstS != -1 && secondS != -1) {
                String quantity = result.substring(firstS + 1, secondS);
                System.out.println("提取的数量字符串: " + quantity);  // 调试输出
                return Integer.parseInt(quantity);
            }
        } catch (Exception e) {
            System.out.println("解析EPC出错: " + e.getMessage());  // 调试输出
            e.printStackTrace();
        }
        return 0;
    }

    private String extractPrefixFromEpc(String epc) {
        try {
            byte[] bytes = new byte[epc.length() / 2];
            for (int i = 0; i < epc.length(); i += 2) {
                bytes[i / 2] = (byte) ((Character.digit(epc.charAt(i), 16) << 4)
                        + Character.digit(epc.charAt(i + 1), 16));
            }
            String result = new String(bytes, StandardCharsets.UTF_8);

            int firstS = result.indexOf('S');
            if (firstS != -1) {
                return result.substring(0, firstS);
            }
        } catch (Exception e) {
            System.out.println("提取前缀出错: " + e.getMessage());  // 调试输出
            e.printStackTrace();
        }
        return "";
    }

    private String generateNewEpc(String prefix, int quantity) {
        // 构建原始字符串
        String originalString = prefix + "S" + quantity + "S";
        System.out.println("生成的原始字符串: " + originalString);  // 调试输出

        // 转换为十六进制，确保长度为24位
        StringBuilder hexString = new StringBuilder();
        byte[] bytes = originalString.getBytes(StandardCharsets.UTF_8);

        for (byte b : bytes) {
            hexString.append(String.format("%02X", b));
        }

        // 如果长度不足24位，随机补全
        while (hexString.length() < 24) {
            hexString.append(Integer.toHexString((int)(Math.random() * 16)));
        }

        // 如果超过24位，截取前24位
        String finalEpc = hexString.substring(0, 24);
        System.out.println("最终生成的EPC: " + finalEpc);  // 调试输出
        return finalEpc;
    }

    @Log(title = "数据推送")
    public AjaxResult dataPush(List<TBaseGoods> goodsList) {
        final String url = "http://172.18.29.101/wms/api/RestJsonService/syncMatBasicInfos";
        ObjectMapper objectMapper = new ObjectMapper();

        // Construct the request body
        Map<String, Object> taskData = new HashMap<>();
        taskData.put("reqCode", generateRandomHexString(14)); // Example request code

        List<Map<String, Object>> dataList = new ArrayList<>();
        for (TBaseGoods good : goodsList) {
            Map<String, Object> dataItem = new HashMap<>();
            dataItem.put("operType", "A");
            dataItem.put("matCode", good.getGoodsId());
            dataItem.put("ownerCode", "8000");
            dataItem.put("matText", good.getGoodsName());
            dataItem.put("matUnit", "EA");
            dataList.add(dataItem);
        }
        taskData.put("data", dataList);

        String requestBody;
        try {
            requestBody = objectMapper.writeValueAsString(taskData);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return AjaxResult.error("JSON processing failed");
        }

        try (CloseableHttpClient httpClient = createHttpClient()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-type", "application/json;charset=UTF-8");
            httpPost.setEntity(new StringEntity(requestBody, "UTF-8"));
            HttpResponse response = httpClient.execute(httpPost);

            String responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
            JsonNode rootNode = objectMapper.readTree(responseString);

            boolean isSuccess = rootNode.path("success").asBoolean();

            if (isSuccess) {
                return AjaxResult.success("数据推送成功");
            } else {
                String errorCode = rootNode.path("code").asText();
                String message = rootNode.path("message").asText();
                return AjaxResult.error("操作失败，错误码：" + errorCode + ", 错误信息：" + message);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("Failed to send POST request");
        }
    }

    private String generateRandomHexString(int len) {
        String hexChars = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(len);
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < len; i++) {
            int index = random.nextInt(hexChars.length());
            sb.append(hexChars.charAt(index));
        }
        return sb.toString();
    }


    private SSLContext createTrustAllSslContext() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }


                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        return sslContext;
    }


    private CloseableHttpClient createHttpClient() throws Exception {
        return HttpClients.custom()
                .setSslcontext(createTrustAllSslContext())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }
}
