package org.jeecg.modules.adweb.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;

import org.jeecg.modules.adweb.common.constant.AdwebConstant;
import org.jeecg.modules.adweb.product.dto.ProductDTO;
import org.jeecg.modules.adweb.product.entity.AdwebProduct;
import org.jeecg.modules.adweb.product.mapper.AdwebProductMapper;
import org.jeecg.modules.adweb.product.service.IAdwebProductService;
import org.jeecg.modules.adweb.site.entity.AdwebSite;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @Description: wp站点产品
 * @Author: jeecg-boot
 * @Date: 2024-12-06
 * @Version: V1.0
 */
@Service
@Slf4j
public class AdwebProductServiceImpl extends ServiceImpl<AdwebProductMapper, AdwebProduct>
        implements IAdwebProductService {

    private final String SOHOEB2B_PUSH_PRODUCT_API = "https://admin.etcpu.com/api/product/product/";

    /**
     * @param productDTO
     * @param adwebSites
     */
    @Override
    public void addOrUpdateProduct(ProductDTO productDTO, AdwebSite adwebSites) {
        // 产品同步时，update 有可能是新增或者更新，根据数据库中记录进行再次判断
        if ("update".equals(productDTO.getActionType())) {
            handleUpdate(productDTO, adwebSites);
        } else if ("delete".equals(productDTO.getActionType())) {
            handleDelete(productDTO, adwebSites);
        } else {
            handleAdd(productDTO, adwebSites);
        }

        pushSohoeB2BProduct(productDTO, adwebSites);
    }

    private void handleUpdate(ProductDTO productDTO, AdwebSite adwebSites) {
        LambdaQueryWrapper<AdwebProduct> productQuery = new LambdaQueryWrapper<>();
        productQuery.eq(AdwebProduct::getProductId, productDTO.getProductId());
        productQuery.eq(AdwebProduct::getSiteCode, adwebSites.getCode());

        AdwebProduct product = this.getOne(productQuery);
        // 执行更新操作
        if (product != null) {
            updateProduct(productDTO, product);
        } else {
            addProduct(productDTO, adwebSites);
        }
    }

    private void handleDelete(ProductDTO productDTO, AdwebSite adwebSites) {
        LambdaUpdateWrapper<AdwebProduct> productQuery = new LambdaUpdateWrapper<>();
        productQuery.eq(AdwebProduct::getProductId, productDTO.getProductId());
        productQuery.eq(AdwebProduct::getSiteCode, adwebSites.getCode());
        productQuery.set(AdwebProduct::getActionType, "delete");
        productQuery.set(AdwebProduct::getRequestTime, productDTO.getRequestTime());
        productQuery.set(AdwebProduct::getAuthorName, productDTO.getAuthorName());

        try {
            boolean isUpdated = this.update(productQuery);
            log.info(
                    "MQ消息删除产品成功, 网站：{}, 产品ID：{}, 是否更新成功：{}",
                    adwebSites.getCode(),
                    productDTO.getProductId(),
                    isUpdated);
        } catch (Exception e) {
            log.error("MQ消息删除产品失败：{}", e.getMessage(), e);
        }
    }

    private void handleAdd(ProductDTO productDTO, AdwebSite adwebSites) {
        AdwebProduct product = new AdwebProduct();
        BeanUtil.copyProperties(productDTO, product);
        product.setSiteCode(adwebSites.getCode());
        this.saveProduct(product);
    }

    private void updateProduct(ProductDTO productDTO, AdwebProduct product) {
        BeanUtil.copyProperties(productDTO, product);

        try {
            this.updateById(product);
            log.info("MQ消息更新产品成功：{}", product);
        } catch (Exception e) {
            log.error("MQ消息更新产品失败：{}", e.getMessage(), e);
        }
    }

    private void addProduct(ProductDTO productDTO, AdwebSite adwebSites) {
        AdwebProduct product = new AdwebProduct();
        BeanUtil.copyProperties(productDTO, product);
        product.setSiteCode(adwebSites.getCode()).setActionType("add");
        this.saveProduct(product);
    }

    private void saveProduct(AdwebProduct product) {
        try {
            this.save(product);

            log.info("MQ消息新增产品成功：{}", product);
        } catch (Exception e) {
            log.error("MQ消息新增产品失败：{}", e.getMessage());
        }
    }

    /**
     * 异步向苏豪通推送产品消息队列
     *
     * <p>TODO 待确定，是否在V3产品中加入推送到苏豪是否成功的状态
     */
    @Async
    protected void pushSohoeB2BProduct(ProductDTO productDTO, AdwebSite adwebSites) {
        // 站点必须处于上线状态，才向苏豪推送产品
        if (AdwebConstant.STATUS.equals(adwebSites.getStatus())) {
            // 向苏豪推送产品添加和更新消息
            String imageBase64 = imageBase64(productDTO.getProductImage());
            JSONObject params = new JSONObject();
            params.put("domain", productDTO.getSiteHost());
            params.put("product_id", productDTO.getProductId());
            params.put("name", productDTO.getProductName());
            params.put("cn_name", productDTO.getProductNameZh());
            params.put("adduser", productDTO.getAuthorName());
            params.put("image", imageBase64);

            log.info("向苏豪推送产品消息,api地址：{}， 参数：{}", SOHOEB2B_PUSH_PRODUCT_API, params);
            try {
                HttpResponse response =
                        HttpRequest.post(SOHOEB2B_PUSH_PRODUCT_API)
                                .header("Content-Type", "application/json")
                                .header(
                                        "Authorization",
                                        "Token f354b8a705c862abeae1f4f96dc55999fb9b3579")
                                .body(params.toString())
                                .execute(true);

                if (response != null && response.getStatus() == 200) {
                    log.info("推送产品到苏豪成功：{}", response.body());
                } else {
                    log.info("推送产品到苏豪失败：{}", response);
                }
            } catch (Exception e) {
                log.info("推送产品到苏豪失败：{}", e.getMessage());
            }
        }
    }

    private String imageBase64(String imgUrl) {
        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream outStream = null;
        HttpURLConnection httpUrl = null;
        try {
            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();
            is = httpUrl.getInputStream();

            outStream = new ByteArrayOutputStream();
            // 创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            // 每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            // 使用一个输入流从buffer里把数据读取出来
            while ((len = is.read(buffer)) != -1) {
                // 用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            // 对字节数组Base64编码
            return Base64Encoder.encode(outStream.toByteArray());
        } catch (Exception e) {
            log.error("图片地址：{}， 下载图片并转base64失败：{}", imgUrl, e.getMessage());
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error("远程下载图片资源失败：{}", e.getMessage());
                }
            }
            if (outStream != null) {
                try {
                    outStream.close();
                } catch (IOException e) {
                    log.error("图片转base64失败：{}", e.getMessage());
                }
            }
            if (httpUrl != null) {
                httpUrl.disconnect();
            }
        }
        return imgUrl;
    }
}
