package com.fs.qw.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.core.domain.R;
import com.fs.common.utils.DateUtils;
import com.fs.qw.domain.QwMaterial;
import com.fs.qw.mapper.QwMaterialMapper;
import com.fs.qw.param.QwMaterialParam;
import com.fs.qw.service.IQwMaterialService;
import com.fs.qw.vo.QwMaterialVO;
import com.fs.qwApi.Result.QwUploadResult;
import com.fs.qwApi.service.QwApiService;
import com.fs.voice.utils.StringUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 素材库Service业务层处理
 *
 * @author fs
 * @date 2024-06-20
 */
@Log4j2
@Service
public class QwMaterialServiceImpl extends ServiceImpl<QwMaterialMapper, QwMaterial> implements IQwMaterialService
{
    @Autowired
    private QwMaterialMapper qwMaterialMapper;

    @Autowired
    private QwApiService qwApiService;

    /**
     * 查询素材库
     *
     * @param materialId 素材库主键
     * @return 素材库
     */
    @Override
    public QwMaterial selectQwMaterialByMaterialId(Long materialId)
    {
        return qwMaterialMapper.selectQwMaterialByMaterialId(materialId);
    }

    /**
     * 查询素材库列表
     *
     * @param param 素材库
     * @return 素材库
     */
    @Override
    public List<QwMaterialVO> selectQwMaterialList(QwMaterialParam param)
    {
        return qwMaterialMapper.selectQwMaterialListVO(param);
    }

    /**
     * 新增素材库
     *
     * @param qwMaterial 素材库
     * @return 结果
     */
    @Override
    public R insertQwMaterial(QwMaterial qwMaterial) throws Exception {
        qwMaterial.setCreateTime(DateUtils.getNowDate());

        //调用企业微信接口 上次临时图片

        if ("text".equals(qwMaterial.getMaterialType())){
            qwMaterialMapper.insertQwMaterial(qwMaterial);
            return R.ok();
        }else if ("image".equals(qwMaterial.getMaterialType())
                ||"video".equals(qwMaterial.getMaterialType())
                ||"file".equals(qwMaterial.getMaterialType())){
            return uploadAndSaveQwMaterial(qwMaterial);
        }

        return R.ok();

    }

    public R uploadAndSaveQwMaterial(QwMaterial qwMaterial){
        try {
            // 将URL转换为文件
            File materialFile = urlToFile(qwMaterial.getMaterialUrl());

            // 上传素材到企业微信
            QwUploadResult uploadResult = qwApiService.upload(materialFile, qwMaterial.getMaterialType(), qwMaterial.getCorpId());

            if (uploadResult.getErrCode() == 0) {
                // 设置素材信息并保存到数据库
                qwMaterial.setMaterialMediaId(uploadResult.getMediaId());
                qwMaterial.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
                qwMaterialMapper.insertQwMaterial(qwMaterial);
                return R.ok();
            } else {
                return R.error("上传"+qwMaterial.getMaterialType()+"失败：" + uploadResult.getErrMsg());
            }
        } catch (Exception e) {
            return R.error("处理"+qwMaterial.getMaterialType()+"时发生异常：" + e.getMessage());
        }
    }

    public QwMaterial uploadAndSaveQwMaterialByDTO(QwMaterial qwMaterial){
        try {
            // 将URL转换为文件
            File materialFile = urlToFile(qwMaterial.getMaterialUrl());

            // 上传素材到企业微信
            QwUploadResult uploadResult = qwApiService.upload(materialFile, qwMaterial.getMaterialType(), qwMaterial.getCorpId());

            if (uploadResult.getErrCode() == 0) {
                // 设置素材信息并保存到数据库
                qwMaterial.setMaterialMediaId(uploadResult.getMediaId());
                qwMaterial.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
                qwMaterialMapper.insertQwMaterial(qwMaterial);
                return qwMaterial;
            } else {
                log.error("上传DTO"+qwMaterial.getMaterialType()+"失败：" + uploadResult.getErrMsg());
                return null;
            }
        } catch (Exception e) {
            log.error("处理DTO"+qwMaterial.getMaterialType()+"时发生异常：" + e.getMessage());
            return null;
        }
    }

    /**
     *  url转临时文件filr
     */
    public static File urlToFile(String fileUrl) throws Exception {

        // 编码文件名部分
        String encodedFileUrl = fileUrl.replace(
                new File(fileUrl).getName(),
                URLEncoder.encode(new File(fileUrl).getName(), "UTF-8")
        );

        // 生成安全的临时文件名
        String fileExtension = getFileExtension(new File(fileUrl).getName());
        String safeFileName = "temp_" + System.currentTimeMillis();
        File tempFile = File.createTempFile(safeFileName, "." + fileExtension);

        // 使用 HttpClient 下载
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(encodedFileUrl);
            request.setHeader("User-Agent", "Mozilla/5.0");
            FileUtils.copyInputStreamToFile(
                    client.execute(request).getEntity().getContent(),
                    tempFile
            );
        } catch (IOException e) {
            tempFile.delete();
            throw new RuntimeException("下载文件失败: " + encodedFileUrl, e);
        }


//        // 从URL中提取文件名，文件后缀
//        String fileExtension = getFileExtension(new File(fileUrl).getName());
//        String fileName = extractFileName(new URL(fileUrl))+new Date().getTime();
//        File tempFile=null;
//        if (!StringUtil.strIsNullOrEmpty(fileExtension)){
//            // 创建一个临时文件
//            tempFile = File.createTempFile(fileName, "."+fileExtension);
//        }else {
//            tempFile = File.createTempFile(fileName, null);
//        }
//
//
//        // 使用 try-with-resources 语句自动关闭资源
//        try (BufferedInputStream in = new BufferedInputStream(new URL(fileUrl).openStream());
//             FileOutputStream out = new FileOutputStream(tempFile)) {
//
//            byte[] buffer = new byte[1024];
//            int len;
//
//            // 读取数据并写入到临时文件
//            while ((len = in.read(buffer)) != -1) {
//                out.write(buffer, 0, len);
//            }
//            out.flush();
//        } catch (IOException e) {
//            // 处理异常，例如删除创建的临时文件
//            tempFile.delete();
//            throw e;
//        }

        return tempFile;
    }

    /**
     *  获取文件名
     */
    private static String extractFileName(URL url) throws Exception {
        String path = url.getPath();
        int lastSlashIndex = path.lastIndexOf('/');
        String fileNameWithExt = path.substring(lastSlashIndex + 1);

        int dotIndex = fileNameWithExt.lastIndexOf('.');
        String baseName;
        if (dotIndex > 0) {
            // 如果有扩展名，移除扩展名
            baseName = fileNameWithExt.substring(0, dotIndex);
        } else {
            // 如果没有扩展名，直接使用文件名
            baseName = fileNameWithExt;
        }

        return baseName;
    }

    /**
     *  获取文件名后缀
     */

    public static String getFileExtension(String fileName) {
        int lastIndex = fileName.lastIndexOf('.');
        if (lastIndex != -1 && lastIndex + 1 < fileName.length()) {
            return fileName.substring(lastIndex + 1);
        }
        return ""; // 如果没有扩展名，返回空字符串
    }
    /**
     * 修改素材库
     *
     * @param qwMaterial 素材库
     * @return 结果
     */
    @Override
    public int updateQwMaterial(QwMaterial qwMaterial)
    {
        qwMaterial.setUpdateTime(DateUtils.getNowDate());
        return qwMaterialMapper.updateQwMaterial(qwMaterial);
    }

    /**
     * 批量删除素材库
     *
     * @param materialIds 需要删除的素材库主键
     * @return 结果
     */
    @Override
    public int deleteQwMaterialByMaterialIds(Long[] materialIds)
    {
        return qwMaterialMapper.deleteQwMaterialByMaterialIds(materialIds);
    }

    /**
     * 删除素材库信息
     *
     * @param materialId 素材库主键
     * @return 结果
     */
    @Override
    public int deleteQwMaterialByMaterialId(Long materialId)
    {
        log.info("删除素材库中信息:{}",qwMaterialMapper.selectQwMaterialByMaterialId(materialId));
        return qwMaterialMapper.deleteQwMaterialByMaterialId(materialId);
    }

    @Override
    public void updateQwMaterialByQw() {

        List<QwMaterial> qwMaterials = qwMaterialMapper.selectQwMaterialListByMediaIdList();


//        qwMaterials.forEach(item->{
//            // 将URL转换为文件
//            File materialFile = null;
//            try {
//                materialFile = urlToFile(item.getMaterialUrl());
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//
//            // 上传素材到企业微信
//            QwUploadResult uploadResult = null;
//            try {
//                uploadResult = qwApiService.upload(
//                        materialFile,
//                        item.getMaterialType(),
//                        item.getCorpId()
//                );
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//
//            if (uploadResult.getErrCode() == 0) {
//                // 设置素材信息
//                item.setMaterialMediaId(uploadResult.getMediaId());
//                item.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
//            } else {
//                log.error("上传失败：{},{}", uploadResult.getErrMsg(), item);
//            }
//        });

        // 创建线程安全的集合用于存储处理结果
        ConcurrentLinkedQueue<QwMaterial> successQueue = new ConcurrentLinkedQueue<>();

        // 创建线程池
        int threadPoolSize = Math.min(8, Runtime.getRuntime().availableProcessors() * 2);
        ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);

        try {
            // 创建并执行所有异步任务
            List<CompletableFuture<Void>> futures = qwMaterials.stream()
                    .filter(item -> "image".equals(item.getMaterialType())
                            || "video".equals(item.getMaterialType())
                            || "file".equals(item.getMaterialType()))
                    .map(item -> CompletableFuture.runAsync(() -> {
                        try {
                            // 将URL转换为文件
                            File materialFile = urlToFile(item.getMaterialUrl());

                            // 上传素材到企业微信
                            QwUploadResult uploadResult = qwApiService.upload(
                                    materialFile,
                                    item.getMaterialType(),
                                    item.getCorpId()
                            );

                            if (uploadResult.getErrCode() == 0) {
                                // 设置素材信息
                                item.setMaterialMediaId(uploadResult.getMediaId());
                                item.setCreatedAt(Long.valueOf(uploadResult.getCreatedAt()));
                                successQueue.add(item);
                            } else {
                                log.error("上传失败：{},{}", uploadResult.getErrMsg(), item);
                            }
                        } catch (Exception e) {
                            log.error("上传失败异常：{},{}", e.getMessage(), item);
                        }
                    }, executor))
                    .collect(Collectors.toList());

            // 等待所有任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            // 批量更新成功的记录
            if (!successQueue.isEmpty()) {
                super.saveOrUpdateBatch(new ArrayList<>(successQueue),300);
            }


        } finally {
            // 关闭线程池
            executor.shutdown();
        }
    }

    @Override
    public QwMaterial selectQwMaterialByMaterialIdByTime(Long materialId) throws Exception {

        return uploadAndSaveQwMaterialByDTO(qwMaterialMapper.selectQwMaterialByMaterialId(materialId));
    }

    @Override
    public QwMaterial selectQwMaterialByMaterialIdByTimeTwo(Long materialId) throws Exception {

        QwMaterial qwMaterial = qwMaterialMapper.selectQwMaterialByMaterialId(materialId);

        Long createdAt = qwMaterial.getCreatedAt();
        boolean isOver48h = createdAt != null
                && (System.currentTimeMillis() / 1000 - createdAt) > 172800;

        if (qwMaterial.getMaterialType() != null && isOver48h) {
            return uploadAndSaveQwMaterialByDTO(qwMaterial);
        }

        return qwMaterial;
    }
}
