package shop.alien.store.util.ai;

import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * 视频审核工具类
 * 调用AI视频审核接口审核视频内容
 */
@Slf4j
@Component
@RefreshScope
@RequiredArgsConstructor
public class AiVideoModerationUtil {

    private final RestTemplate restTemplate;

    /**
     * 视频上传接口地址
     */
    @Value("${ai.service.video-submit-url}")
    private String videoSubmitUrl;

    /**
     * 视频审查接口地址
     */
    @Value("${ai.service.video-status-url}")
    private String videoStatusUrl;

    /**
     * 轮询间隔（毫秒）
     */
    @Value("${ai.service.video-poll-interval:2000}")
    private long pollInterval;

    /**
     * 最大轮询次数
     */
    @Value("${ai.service.video-max-poll-count:30}")
    private int maxPollCount;

    /**
     * 审核结果类
     */
    public static class VideoAuditResult {
        private boolean passed;
        private String failureReason;
        private String taskId;
        private JSONObject rawResult;

        public VideoAuditResult(boolean passed, String failureReason) {
            this.passed = passed;
            this.failureReason = failureReason;
        }

        public VideoAuditResult(boolean passed, String failureReason, String taskId, JSONObject rawResult) {
            this.passed = passed;
            this.failureReason = failureReason;
            this.taskId = taskId;
            this.rawResult = rawResult;
        }

        public boolean isPassed() {
            return passed;
        }

        public String getFailureReason() {
            return failureReason;
        }

        public String getTaskId() {
            return taskId;
        }

        public JSONObject getRawResult() {
            return rawResult;
        }
    }

    /**
     * 审核视频内容
     *
     * @param videoUrls 视频URL列表
     * @return 审核结果
     */
    public VideoAuditResult auditVideos(List<String> videoUrls) {
        if (videoUrls == null || videoUrls.isEmpty()) {
            log.info("视频URL列表为空，跳过审核");
            return new VideoAuditResult(true, null);
        }

        log.info("开始审核视频：videoCount={}", videoUrls.size());

        try {
            List<VideoAuditResult> results = new ArrayList<>();
            for (String videoUrl : videoUrls) {
                if (StringUtils.hasText(videoUrl)) {
                    VideoAuditResult result = auditSingleVideo(videoUrl);
                    results.add(result);
                }
            }

            // 如果任何一个视频审核失败，整体审核失败
            for (VideoAuditResult result : results) {
                if (!result.isPassed()) {
                    log.warn("视频审核失败：{}", result.getFailureReason());
                    return result;
                }
            }

            log.info("所有视频审核通过");
            return new VideoAuditResult(true, null);

        } catch (Exception e) {
            log.error("审核视频异常", e);
            return new VideoAuditResult(false, "审核服务异常：" + e.getMessage());
        }
    }

    /**
     * 审核单个视频
     *
     * @param videoUrl 视频URL
     * @return 审核结果
     */
    private VideoAuditResult auditSingleVideo(String videoUrl) {
        try {
            // 1. 提交视频审核任务
            String taskId = submitVideo(videoUrl);
            if (taskId == null) {
                return new VideoAuditResult(false, "视频提交失败");
            }

            log.info("视频提交成功，taskId={}, videoUrl={}", taskId, videoUrl);

            // 2. 轮询审核状态
            return pollVideoStatus(taskId, videoUrl);

        } catch (Exception e) {
            log.error("审核视频异常，videoUrl={}", videoUrl, e);
            return new VideoAuditResult(false, "审核服务异常：" + e.getMessage());
        }
    }

    /**
     * 提交视频审核任务
     *
     * @param videoUrl 视频URL
     * @return 任务ID
     */
    private String submitVideo(String videoUrl) {
        try {
            // 构建 form-data 请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            // 构建 form-data 请求体，兼容服务端可能的三种参数名
            MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
            formData.add("videoUrl", videoUrl);
            formData.add("video_path", videoUrl);
            formData.add("video_url", videoUrl);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, headers);

            log.info("提交视频审核任务：url={}, videoUrl={}", videoSubmitUrl, videoUrl);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(videoSubmitUrl, requestEntity, String.class);

            if (response.getStatusCode() == HttpStatus.OK) {
                String responseBody = response.getBody();
                log.info("视频提交接口响应：{}", responseBody);

                if (StringUtils.hasText(responseBody)) {
                    JSONObject jsonResponse = JSONObject.parseObject(responseBody);
                    String taskId = jsonResponse.getString("task_id");
                    if (StringUtils.hasText(taskId)) {
                        return taskId;
                    } else {
                        log.error("视频提交接口返回的task_id为空");
                        return null;
                    }
                } else {
                    log.error("视频提交接口返回空响应");
                    return null;
                }
            } else {
                log.error("视频提交接口调用失败，状态码：{}", response.getStatusCode());
                return null;
            }

        } catch (org.springframework.web.client.HttpClientErrorException e) {
            log.error("调用视频提交接口异常，status={}, body={}", e.getStatusCode(), e.getResponseBodyAsString(), e);
            return null;
        } catch (Exception e) {
            log.error("调用视频提交接口异常", e);
            return null;
        }
    }

    /**
     * 轮询视频审核状态
     *
     * @param taskId 任务ID
     * @param videoUrl 视频URL（用于日志）
     * @return 审核结果
     */
    private VideoAuditResult pollVideoStatus(String taskId, String videoUrl) {
        int pollCount = 0;
        while (pollCount < maxPollCount) {
            try {
                // 等待一段时间再查询
                if (pollCount > 0) {
                    Thread.sleep(pollInterval);
                }

                String statusUrl = videoStatusUrl + "/" + taskId;
                log.info("查询视频审核状态：url={}, taskId={}, pollCount={}", statusUrl, taskId, pollCount + 1);

                ResponseEntity<String> response = restTemplate.getForEntity(statusUrl, String.class);

                if (response.getStatusCode() == HttpStatus.OK) {
                    String responseBody = response.getBody();
                    log.info("视频审核状态接口响应：{}", responseBody);

                    if (StringUtils.hasText(responseBody)) {
                        JSONObject jsonResponse = JSONObject.parseObject(responseBody);
                        String status = jsonResponse.getString("status");

                        if ("completed".equals(status)) {
                            // 审核完成，解析结果
                            return parseVideoAuditResult(jsonResponse, taskId);
                        } else if ("failed".equals(status) || "error".equals(status)) {
                            // 审核失败
                            String error = jsonResponse.getString("error");
                            log.error("视频审核失败，taskId={}, error={}", taskId, error);
                            return new VideoAuditResult(false, "视频审核失败：" + (error != null ? error : "未知错误"), taskId, jsonResponse);
                        } else {
                            // 审核中，继续轮询
                            log.info("视频审核中，taskId={}, status={}, 继续等待...", taskId, status);
                            pollCount++;
                        }
                    } else {
                        log.error("视频审核状态接口返回空响应");
                        return new VideoAuditResult(false, "审核状态接口返回空响应");
                    }
                } else {
                    log.error("视频审核状态接口调用失败，状态码：{}", response.getStatusCode());
                    return new VideoAuditResult(false, "审核状态接口调用失败，状态码：" + response.getStatusCode());
                }

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("轮询视频审核状态被中断，taskId={}", taskId, e);
                return new VideoAuditResult(false, "审核被中断");
            } catch (Exception e) {
                log.error("查询视频审核状态异常，taskId={}", taskId, e);
                pollCount++;
                // 继续重试
            }
        }

        log.error("视频审核超时，taskId={}, maxPollCount={}", taskId, maxPollCount);
        return new VideoAuditResult(false, "视频审核超时");
    }

    /**
     * 解析视频审核结果
     *
     * @param jsonResponse API响应JSON
     * @param taskId 任务ID
     * @return 审核结果
     */
    private VideoAuditResult parseVideoAuditResult(JSONObject jsonResponse, String taskId) {
        try {
            JSONObject result = jsonResponse.getJSONObject("result");
            if (result == null) {
                log.warn("视频审核结果中result字段为空");
                return new VideoAuditResult(false, "审核结果格式错误：result字段为空", taskId, jsonResponse);
            }

            Boolean flagged = result.getBoolean("flagged");
            String riskLevel = result.getString("risk_level");
            String summary = result.getString("summary");

            if (flagged != null && flagged) {
                // 有违规内容，审核失败
                List<String> violationReasons = new ArrayList<>();
                if (StringUtils.hasText(riskLevel)) {
                    violationReasons.add("风险等级：" + riskLevel);
                }
                if (StringUtils.hasText(summary)) {
                    violationReasons.add(summary);
                }

                // 解析违规证据
                com.alibaba.fastjson2.JSONArray evidence = result.getJSONArray("evidence");
                if (evidence != null && !evidence.isEmpty()) {
                    List<String> evidenceReasons = new ArrayList<>();
                    for (int i = 0; i < evidence.size(); i++) {
                        JSONObject item = evidence.getJSONObject(i);
                        if (item != null) {
                            String reason = item.getString("reason");
                            String timeOffset = item.getString("time_offset");
                            if (StringUtils.hasText(reason)) {
                                String evidenceReason = StringUtils.hasText(timeOffset)
                                    ? String.format("时间点%s: %s", timeOffset, reason)
                                    : reason;
                                evidenceReasons.add(evidenceReason);
                            }
                        }
                    }
                    if (!evidenceReasons.isEmpty()) {
                        violationReasons.add("违规证据：" + String.join("; ", evidenceReasons));
                    }
                }

                String failureReason = String.join("; ", violationReasons);
                if (failureReason.isEmpty()) {
                    failureReason = "视频内容违规";
                }

                log.warn("视频审核失败：{}", failureReason);
                return new VideoAuditResult(false, failureReason, taskId, jsonResponse);
            } else {
                // 无违规内容，审核通过
                log.info("视频审核通过：taskId={}", taskId);
                return new VideoAuditResult(true, null, taskId, jsonResponse);
            }

        } catch (Exception e) {
            log.error("解析视频审核结果异常", e);
            return new VideoAuditResult(false, "解析审核结果异常：" + e.getMessage(), taskId, jsonResponse);
        }
    }
}

