package com.imooc.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.imooc.base.BaseInfoProperties;
import com.imooc.bo.VlogBO;
import com.imooc.config.MinIOConfig;
import com.imooc.enums.YesOrNo;
import com.imooc.grace.result.GraceJSONResult;
import com.imooc.service.VlogService;
import com.imooc.utils.MinIOUtils;
import com.imooc.utils.PagedGridResult;
import com.qcloud.vod.model.VodUploadResponse;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import com.imooc.utils.QcCloud;

import java.util.List;
import java.util.Map;

@Slf4j
@Api(tags = "VlogController 短视频相关业务功能的接口")
@RequestMapping("vlog")
@RestController
@RefreshScope
public class VlogController extends BaseInfoProperties {
    @Autowired
    private VlogService vlogService;
    @Autowired
    private QcCloud qcCloud;
    @Autowired
    private MinIOConfig minIOConfig;

    @PostMapping("vodCallBack")
    public GraceJSONResult vodCallBack(@RequestBody Map<String, Object> callbackData) {
        try {
            // 解析回调事件类型
            String eventType = (String) callbackData.get("EventType");
            log.info("收到腾讯云 VOD 回调, 事件类型: {}", eventType);
            log.info(callbackData.toString());

            if ("ProcedureStateChanged".equals(eventType)) {
                // 获取 ProcedureStateChangeEvent
                Object eventObject = callbackData.get("ProcedureStateChangeEvent");
                if (eventObject instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Map<String, Object> procedureStateChangeEvent = (Map<String, Object>) eventObject;
                    String fileId = (String) procedureStateChangeEvent.get("FileId");
                    String fileUrl = (String) procedureStateChangeEvent.get("FileUrl"); // 原视频地址
                    String status = (String) procedureStateChangeEvent.get("Status"); // FINISH
                    // 只处理完成状态
                    if ("FINISH".equals(status)) {
                        // 获取 MediaProcessResultSet，可能包含任务流信息
                        List<Map<String, Object>> mediaProcessResultSet =
                                (List<Map<String, Object>>) procedureStateChangeEvent.get("MediaProcessResultSet");

                        if (mediaProcessResultSet != null) {
                            String coverUrl=null; // 首帧图
                            String transVdUrl=null; // 转码后的视频地址
                            for (Map<String, Object> processResult : mediaProcessResultSet) {
                                String type = (String) processResult.get("Type");
                                if ("CoverBySnapshot".equals(type)) {
                                    // 任务流：首帧截图
                                    Map<String, Object> coverBySnapshotTask =
                                            (Map<String, Object>) processResult.get("CoverBySnapshotTask");
                                    Map<String, Object> output = (Map<String, Object>) coverBySnapshotTask.get("Output");
                                    coverUrl = (String) output.get("CoverUrl"); // 正确获取 CoverUrl

                                }
                                if("Transcode".equals(type)){
                                    // 拿到output中的url
                                    Map<String, Object> TranscodeTask =
                                            (Map<String, Object>) processResult.get("TranscodeTask");
                                    Map<String, Object> output = (Map<String, Object>) TranscodeTask.get("Output");
                                    transVdUrl = (String) output.get("Url");
                                }
                            }
                            log.info("任务流 [截取首帧，视频转码] 完成, FileId: {}, 封面图 URL: {},视频地址: {}", fileId, coverUrl,transVdUrl);
                            // TODO: 更新数据库，存储首帧图,设置云端地址，删除minio视频文件
                            vlogService.updateVlogFirstImg(fileId,coverUrl,transVdUrl);

                        } else {
                            log.warn("MediaProcessResultSet 为空，回调数据: {}", callbackData);
                        }
                    }
                    log.info("任务流完成, FileId: {}, Status: {}", fileId, status);
                } else {
                    log.warn("ProcedureStateChangeEvent 为空或格式错误，回调数据: {}", callbackData);
                }
            }
            if("ReviewAudioVideoComplete".equals(eventType)){
                //处理审核结果
                Map<String, Object> reviewEvent = (Map<String, Object>) callbackData.get("ReviewAudioVideoCompleteEvent");
                if (reviewEvent != null) {
                    String status = (String) reviewEvent.get("Status"); // FINISH
                    if ("FINISH".equals(status)) {
                        Map<String, Object> input = (Map<String, Object>) reviewEvent.get("Input");
                        String fileId = (String) input.get("FileId"); // 查询的唯一标识
                        // 获取审核结果
                        Map<String, Object> output = (Map<String, Object>) reviewEvent.get("Output");
                        String suggestion = (String) output.get("Suggestion");
                        if ("block".equals(suggestion)) {
                            // 审核不通过，修改视频状态为2，写入reason，发送站内消息，告知审核结果
                            // label
                            //Porn：色情；
                            //Terror：暴力；
                            //Polity：不适宜的信息；
                            //Ad：广告；
                            //Illegal：违法；
                            //Abuse：谩骂；
                            //Moan：娇喘。
                            String label = (String) output.get("Label"); // 违规内容
                            String subLabel = (String) output.get("SubLabel"); // 违规子标签
                            log.info("视频文件 {} 审核驳回, 原因: {} - {}", fileId, label, subLabel);
                            // TODO: 更新数据库,发送站内信
                            vlogService.updateVlogStatus(fileId,2,label);
                        } else if ("pass".equals(suggestion)) {
                            // 审核通过，处理通过逻辑,修改视频状态为1，发送站内消息，告知审核结果
                            log.info("视频文件 {} 审核通过", fileId);
                            // TODO: 更新数据库，发送站内信
                            vlogService.updateVlogStatus(fileId,1,"通过");

                        } else if ("review".equals(suggestion)){
                            // 建议复审，修改状态为3，发送站内消息，告知审核结果
                            String label = (String) output.get("Label"); // 违规内容
                            String subLabel = (String) output.get("SubLabel"); // 违规子标签
                            log.info("视频文件 {} 建议复审, 原因: {} - {}", fileId, label, subLabel);
                            // TODO: 更新数据库，发送站内信
                            vlogService.updateVlogStatus(fileId,3,"等待复审");

                        }
                    }
                }
            }
            // 处理完成，返回成功，防止腾讯云重复发送回调
            return GraceJSONResult.ok();
        } catch (Exception e) {
            log.error("处理腾讯云 VOD 回调异常: ", e);
            return GraceJSONResult.error();
        }
    }

    @PostMapping("publish")
    public GraceJSONResult publish(@RequestBody VlogBO vlogBO) throws Exception {
        String url = vlogBO.getUrl();
        log.info("未审核视频地址:"+url);
        String fileName = url.substring(url.lastIndexOf("/") + 1);
        log.info("视频文件名称:"+fileName);
        log.info("开始上传腾讯云点播:"+fileName);
        String fileId = qcCloud.uploadViaTempFile(fileName);
        log.info("视频发布ID:"+fileId);
        vlogBO.setFileId(fileId);
        // 删除minio文件
//        MinIOUtils.removeFile(minIOConfig.getBucketName(),fileName);
//        log.info("删除minio文件："+fileName);

        // FIXME 校验VlogBO
        vlogService.createVlog(vlogBO);

        return GraceJSONResult.ok();
    }

    @GetMapping("indexList")
    public GraceJSONResult indexList(@RequestParam(defaultValue = "") String userId,
                                     @RequestParam(defaultValue = "") String search,
                                     @RequestParam(defaultValue = "") String cityCode,
                                     @RequestParam(defaultValue = "") String status,
                                     @RequestParam Integer page,
                                     @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.getIndexVlogList(userId, search, cityCode,status, page, pageSize);
        return GraceJSONResult.ok(gridResult);
    }

    @GetMapping("detail")
    public GraceJSONResult detail(@RequestParam(defaultValue = "") String userId,
                                  @RequestParam String vlogId) {
        return GraceJSONResult.ok(vlogService.getVlogDetailById(userId, vlogId));
    }
    @PostMapping("changeVlogStatus")
    public GraceJSONResult changeVlogStatus(@RequestParam String userId,
                                            @RequestParam String vlogId,
                                            @RequestParam Integer status) {
        vlogService.changeVlogStatus(userId, vlogId,status);
        return GraceJSONResult.ok();
    }

    @PostMapping("changeToPrivate")
    public GraceJSONResult changeToPrivate(@RequestParam String userId,
                                           @RequestParam String vlogId) {
        vlogService.changeToPrivateOrPublic(userId,
                                            vlogId,
                                            YesOrNo.YES.type);
        return GraceJSONResult.ok();
    }

    @PostMapping("changeToPublic")
    public GraceJSONResult changeToPublic(@RequestParam String userId,
                                           @RequestParam String vlogId) {
        vlogService.changeToPrivateOrPublic(userId,
                vlogId,
                YesOrNo.NO.type);
        return GraceJSONResult.ok();
    }



    @GetMapping("myPublicList")
    public GraceJSONResult myPublicList(@RequestParam String userId,
                                        @RequestParam(defaultValue = "") String myId,
                                     @RequestParam Integer page,
                                     @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
                                                                myId,
                                                                page,
                                                                pageSize,
                                                                YesOrNo.NO.type);
        return GraceJSONResult.ok(gridResult);
    }

    @GetMapping("myPrivateList")
    public GraceJSONResult myPrivateList(@RequestParam String userId,
                                         @RequestParam(defaultValue = "") String myId,
                                        @RequestParam Integer page,
                                        @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.queryMyVlogList(userId,
                myId,
                page,
                pageSize,
                YesOrNo.YES.type);
        return GraceJSONResult.ok(gridResult);
    }

    @GetMapping("myLikedList")
    public GraceJSONResult myLikedList(@RequestParam String userId,
                                       @RequestParam(defaultValue = "") String myId,
                                         @RequestParam Integer page,
                                         @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.getMyLikedVlogList(userId,
                                                                    myId,
                                                                    page,
                                                                    pageSize);
        return GraceJSONResult.ok(gridResult);
    }

    @Value(("${nacos.counts}"))
    private Integer nacosConuts;


    @PostMapping("like")
    public GraceJSONResult like(@RequestParam String userId,
                                 @RequestParam String vlogerId,
                                 @RequestParam String vlogId) {

        // 我点赞的视频，关联关系保存到数据库
        vlogService.userLikeVlog(userId, vlogId);

        // 点赞后，视频和视频发布者的获赞都会 +1
        redis.increment(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
        redis.increment(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);

        // 我点赞的视频，需要在redis中保存关联关系
        redis.set(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId, "1");

        log.info("nacosConuts="+nacosConuts);

        String countsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
        Integer counts=0;
        if (StringUtils.isNotBlank(countsStr)){

            counts=Integer.valueOf(countsStr);
            if (counts>=nacosConuts){

                vlogService.flushCounts(vlogId, counts);
            }
        }

        return GraceJSONResult.ok();
    }


    @PostMapping("unlike")
    public GraceJSONResult unlike(@RequestParam String userId,
                                @RequestParam String vlogerId,
                                @RequestParam String vlogId) {

        // 我取消点赞的视频，关联关系删除
        vlogService.userUnLikeVlog(userId, vlogId);

        redis.decrement(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + vlogerId, 1);
        redis.decrement(REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId, 1);
        redis.del(REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);

        return GraceJSONResult.ok();
    }

    @PostMapping("totalLikedCounts")
    public GraceJSONResult totalLikedCounts(@RequestParam String vlogId) {
        return GraceJSONResult.ok(vlogService.getVlogBeLikedCounts(vlogId));
    }

    @GetMapping("followList")
    public GraceJSONResult followList(@RequestParam String myId,
                                       @RequestParam Integer page,
                                       @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.getMyFollowVlogList(myId,
                                                                    page,
                                                                    pageSize);
        return GraceJSONResult.ok(gridResult);
    }

    @GetMapping("friendList")
    public GraceJSONResult friendList(@RequestParam String myId,
                                      @RequestParam Integer page,
                                      @RequestParam Integer pageSize) {

        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult gridResult = vlogService.getMyFriendVlogList(myId,
                                                                    page,
                                                                    pageSize);
        return GraceJSONResult.ok(gridResult);
    }
}
