package com.moka.gdtauto.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moka.gdtauto.client.TencentAdsApiClientFactory;
import com.moka.gdtauto.entity.TencentAssetDrama;
import com.moka.gdtauto.entity.TencentImages;
import com.moka.gdtauto.mapper.TencentImagesMapper;
import com.moka.gdtauto.service.TencentAssetDramaService;
import com.moka.gdtauto.service.TencentImagesService;
import com.moka.gdtauto.util.ImageWatermarkUtil;
import com.tencent.ads.model.v3.ImagesAddResponseData;
import com.tencent.ads.v3.TencentAds;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.util.Base64;

/**
 * 腾讯广告图片Service实现类
 *
 * @author moka
 * @since 2026-02-06
 */
@Slf4j
@Service
public class TencentImagesServiceImpl extends ServiceImpl<TencentImagesMapper, TencentImages> 
        implements TencentImagesService {

    @Autowired
    private TencentAdsApiClientFactory clientFactory;

    @Autowired
    private TencentAssetDramaService dramaService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TencentImages uploadImage(MultipartFile file, Long accountId, 
                                      Boolean hasWatermark, Long dramaId, String description) {
        TencentImages imageRecord = new TencentImages();
        imageRecord.setAccountId(accountId);
        imageRecord.setOriginalFilename(file.getOriginalFilename());
        imageRecord.setHasWatermark(hasWatermark != null && hasWatermark);
        imageRecord.setDramaId(dramaId);
        imageRecord.setDescription(description);
        imageRecord.setCreatedTime(LocalDateTime.now());
        imageRecord.setUpdatedTime(LocalDateTime.now());

        try {
            // 1. 获取原始图片字节数据
            byte[] originalImageBytes = file.getBytes();
            log.info("获取原始图片数据成功，大小: {} bytes", originalImageBytes.length);

            byte[] finalImageBytes = originalImageBytes;

            // 2. 如果需要添加水印，在内存中处理
            if (hasWatermark != null && hasWatermark && dramaId != null) {
                TencentAssetDrama drama = dramaService.getById(dramaId);
                if (drama != null && drama.getMarketingAssetName() != null) {
                    log.info("开始在内存中添加水印，剧名: {}", drama.getMarketingAssetName());
                    
                    // 从字节数组读取图片到BufferedImage
                    BufferedImage watermarkedImage = ImageWatermarkUtil.addWatermarkInMemory(
                        originalImageBytes, 
                        drama.getMarketingAssetName(),
                        48,  // 字体大小
                        50,  // x坐标 - 左上角
                        50   // y坐标 - 左上角
                    );
                    
                    // 将BufferedImage转换回字节数组
                    finalImageBytes = bufferedImageToBytes(watermarkedImage, getImageFormat(file.getOriginalFilename()));
                    
                    imageRecord.setWatermarkText(drama.getMarketingAssetName());
                    log.info("水印添加成功: {}，新图片大小: {} bytes", drama.getMarketingAssetName(), finalImageBytes.length);
                }
            }

            // 3. 计算MD5签名
            String signature = calculateMD5(finalImageBytes);
            log.info("图片MD5签名: {}", signature);

            // 4. 转换为Base64编码
            String base64Image = Base64.getEncoder().encodeToString(finalImageBytes);
            log.info("Base64编码完成，长度: {}", base64Image.length());

            // 5. 获取TencentAds客户端
            TencentAds tencentAds = clientFactory.getTencentAdsWithoutUserToken("12458", 33453856L);
            log.info("开始上传图片到腾讯广告，账户ID: {}", accountId);

            // 6. 调用腾讯广告API上传图片（使用UPLOAD_TYPE_BYTES方式）
            ImagesAddResponseData response = tencentAds.images()
                .imagesAdd(
                    "UPLOAD_TYPE_BYTES",  // 使用字节方式上传
                    signature,
                    accountId,
                    null,
                    null,                  // file参数为null
                    base64Image,           // 传入Base64编码的图片
                    null,
                    description,
                    null,
                    null,
                    null
                );

            // 7. 保存上传结果
            if (response != null) {
                imageRecord.setImageId(response.getImageId());
                imageRecord.setImageWidth(response.getImageWidth() != null ? response.getImageWidth().intValue() : null);
                imageRecord.setImageHeight(response.getImageHeight() != null ? response.getImageHeight().intValue() : null);
                imageRecord.setImageFileSize(response.getImageFileSize());
                imageRecord.setImageType(response.getImageType() != null ? response.getImageType().toString() : null);
                imageRecord.setPreviewUrl(response.getPreviewUrl());
                imageRecord.setUploadStatus("SUCCESS");
                
                log.info("图片上传成功 - ID: {}, 宽度: {}px, 高度: {}px, 大小: {}B, 类型: {}", 
                    response.getImageId(), 
                    response.getImageWidth(), 
                    response.getImageHeight(), 
                    response.getImageFileSize(), 
                    response.getImageType());
            } else {
                imageRecord.setUploadStatus("FAILED");
                imageRecord.setErrorMessage("上传返回结果为空");
                log.error("图片上传失败: 返回结果为空");
            }

        } catch (Exception e) {
            log.error("图片上传失败", e);
            imageRecord.setUploadStatus("FAILED");
            imageRecord.setErrorMessage(e.getMessage());
        }

        // 8. 保存记录到数据库
        this.save(imageRecord);
        log.info("图片记录保存成功，ID: {}", imageRecord.getId());

        return imageRecord;
    }

    /**
     * 计算字节数组的MD5签名
     */
    private String calculateMD5(byte[] bytes) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(bytes);
        byte[] digest = md.digest();
        BigInteger bigInt = new BigInteger(1, digest);
        String hashtext = bigInt.toString(16);
        // 补齐前导0
        while (hashtext.length() < 32) {
            hashtext = "0" + hashtext;
        }
        return hashtext;
    }

    /**
     * 将BufferedImage转换为字节数组
     */
    private byte[] bufferedImageToBytes(BufferedImage image, String formatName) throws Exception {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(image, formatName, baos);
            baos.flush();
            return baos.toByteArray();
        }
    }

    /**
     * 获取图片格式名称
     */
    private String getImageFormat(String filename) {
        if (filename == null || !filename.contains(".")) {
            return "jpg";
        }
        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
        switch (extension) {
            case "jpeg":
                return "jpg";
            case "png":
                return "png";
            case "gif":
                return "gif";
            case "bmp":
                return "bmp";
            default:
                return "jpg";
        }
    }
}
