package cn.com.ctop.common.module.service.impl;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.entity.FileInfo;
import cn.com.ctop.common.module.entity.Project;
import cn.com.ctop.common.module.entity.UserAllocation;
import cn.com.ctop.common.module.mapper.FileInfoMapper;
import cn.com.ctop.common.module.service.*;
import cn.com.ctop.common.module.utils.BytedanceInterfaceConstant;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.common.module.utils.HttpUtils;
import cn.com.ctop.common.module.utils.PropertiesUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 文件信息
 * @Author: jeecg-boot
 * @Date: 2019-07-28
 * @Version: V1.0
 */
@Slf4j
@Service
@Primary
public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> implements IFileInfoService {
    @Value("${jeecg.path.image-upload}")
    private String imageUploadPath;
    @Value("${jeecg.path.video-upload}")
    private String videoUploadPath;
    @Autowired
    FileInfoMapper fileInfoMapper;
    @Resource
    private ICtopOauthTokenService ctopOauthTokenService;
    @Autowired
    private IUserAllocationService userAllocationService;
    @Autowired
    private IMessageTemplate messageTemplate;
    @Autowired
    private ISendMessageService sendMessageService;
    @Autowired
    private IProjectService projectService;

    @Override
    public void uploadVideoToBytedance(String accountId, String videoUrl, String userId, String materialName) {
        try {
            CtopOauthToken token = ctopOauthTokenService.getOauthTokenByAccountId(accountId);
            JSONObject jsonObject = videoUpload(token, videoUrl);
            if (!Check.isNull(jsonObject)) {
                Integer code = jsonObject.getInteger("code");
                if (code == 0) {
                    log.info("头条上传素材成功，返回信息：{},accountId:{}", jsonObject, accountId);
                } else {
                    log.error("头条上传素材失败，返回信息：{},accountId:{}", jsonObject, accountId);
                    UserAllocation allocation = userAllocationService.getByAccountId(Long.valueOf(accountId));
                    Project project = projectService.getById(allocation.getProjectId());
                    String message = messageTemplate.getMaterialSyncTemplate(project.getProjectName(), accountId, allocation.getAuthName(), materialName, jsonObject.getString("message"));
                    sendMessageService.sendMessage(userId, message);
                }

            } else {
                log.info("头条上传素材返回结果为空，返回信息：{},accountId:{}", jsonObject, accountId);
            }

        } catch (Exception e) {
            log.error("头条上传视频文件失败，accountId:{}", accountId);
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> uploadImageToBytedance(String accountId, String imageUrl) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            CtopOauthToken token = ctopOauthTokenService.getOauthTokenByAccountId(accountId);
            JSONObject jsonObject = imageUpload(token, String.valueOf(token.getAccountId()), imageUrl);
            log.info("头条上传图片素材返回信息：{}，accountId：{}", jsonObject, accountId);
        } catch (Exception e) {
            log.error("头条上传图片文件失败，accountId:{}", accountId);
            log.error(e.getMessage(), e);
        }

        return resultMap;
    }

    @Override
    public List<FileInfo> getFileInfoByMd5(String md5) {
        QueryWrapper<FileInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5).orderByDesc("create_time");
        return fileInfoMapper.selectList(queryWrapper);
    }

    @Override
    public Map<String, Object> getCreativeWords(Long accountId) {
        CtopOauthToken token = ctopOauthTokenService.getOauthTokenByAccountId(accountId + "");
        return getCreativeWord(token, accountId);
    }

    @Override
    public JSONObject getSiteList(Long accountId) {
        return null;
    }

    @Override
    public JSONObject getCreativeWord(CtopOauthToken token, Long advertiserId) {
        // 请求地址
        String url = "https://ad.toutiao.com/open_api/2/tools/creative_word/select/";
        // 请求参数
        JSONObject data = new JSONObject();
        data.put("advertiser_id", advertiserId);
        JSONObject resultObject = HttpUtils.bytedanceGetRequest(token.getAccessToken(), url, data);
        JSONArray creativeWords = resultObject.getJSONObject("data").getJSONArray("creative_word");
        resultObject.remove("data");
        JSONArray array = new JSONArray();
        if (null != creativeWords && !creativeWords.isEmpty()) {
            creativeWords.forEach(word -> {
                JSONObject getWord = (JSONObject) word;
                String name = getWord.getString("name");
                getWord.remove("words");
                getWord.put("name", name);
                getWord.remove("words");
                getWord.remove("max_word_len");
                String status = getWord.getString("status");
                if (null != status && "CREATIVE_WORD_STATUS_APPROVE".equals(status.trim())) {
                    array.add(getWord);
                }
            });
        }
        resultObject.put("creative_word", array);
        return resultObject;
    }

    /**
     * 行动号召数据获取
     *
     * @return
     */
    @Override
    public JSONObject getActionText(Long accountId, String landingType) {
        CtopOauthToken token = ctopOauthTokenService.getTokenByAccountId(accountId);
        // 请求地址
        String url = "https://ad.oceanengine.com/open_api/2/tools/action_text/get/";
        // 请求参数
        JSONObject data = new JSONObject();
        data.put("advertiser_id", accountId);
        data.put("landing_type", landingType);
        return HttpUtils.bytedanceGetRequest(token.getAccessToken(), url, data);
    }

    private JSONObject imageUpload(CtopOauthToken token, String advertiserId, String imageUrl) {
        // 请求地址
        String url = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_file_image_ad");
        // 构造请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Access-Token", token.getAccessToken());
        MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
        // 其他参数
        entityBuilder.addTextBody("advertiser_id", advertiserId);
        entityBuilder.addTextBody("upload_type", BytedanceInterfaceConstant.UPLOAD_TYPE_BY_URL);
        entityBuilder.addTextBody("image_url", imageUrl);

        HttpEntity entity = entityBuilder.build();
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        try {
            client = HttpClientBuilder.create().build();
            httpPost.setURI(URI.create(url));
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuilder buffer = new StringBuilder();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    buffer.append(line);
                }
                bufferedReader.close();
                return JSONObject.parseObject(buffer.toString());
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                if (null != client) {
                    client.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }


    @Override
    public String downLoadByUrl(String fileUrl) {
        //获取文件名，文件名实际上在URL中可以找到
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        //这里服务器上要将此图保存的路径
        String savePath = this.imageUploadPath + fileName;
        try {
            /*将网络资源地址传给,即赋值给url*/
            URL url = new URL(fileUrl);
            /*此为联系获得网络资源的固定格式用法，以便后面的in变量获得url截取网络资源的输入流*/
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            DataInputStream in = new DataInputStream(connection.getInputStream());
            /*此处也可用BufferedInputStream与BufferedOutputStream*/
            DataOutputStream out = new DataOutputStream(new FileOutputStream(savePath));
            /*将参数savePath，即将截取的图片的存储在本地地址赋值给out输出流所指定的地址*/
            byte[] buffer = new byte[4096];
            int count = 0;
            /*将输入流以字节的形式读取并写入buffer中*/
            while ((count = in.read(buffer)) > 0) {
                out.write(buffer, 0, count);
            }
            out.close();/*后面三行为关闭输入输出流以及网络资源的固定格式*/
            in.close();
            connection.disconnect();
            //返回内容是保存后的完整的URL
            /*网络资源截取并存储本地成功返回true*/
            return savePath;

        } catch (Exception e) {
            return null;
        }
    }


    private JSONObject videoUpload(CtopOauthToken token, String videoPath) {
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        // 请求地址
        String url = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_file_video_ad");
        // 构造请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Access-Token", token.getAccessToken());
        // 文件参数
        try {
            FileBody file = new FileBody(new File(videoPath));
            MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
                    .addPart("video_file", file);
            // 其他参数
            entityBuilder.addTextBody("advertiser_id", String.valueOf(token.getAccountId()));
            entityBuilder.addTextBody("video_signature", DigestUtils.md5Hex(new FileInputStream(new File(videoPath))));
            HttpEntity entity = entityBuilder.build();
            client = HttpClientBuilder.create().build();
            httpPost.setURI(URI.create(url));
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuilder result = new StringBuilder();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    result.append(line);
                }
                bufferedReader.close();
                return JSONObject.parseObject(result.toString());
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                if (null != client) {
                    client.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

}
