package com.fs.live.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.fs.common.vo.LiveVo;
import com.fs.common.constant.LiveKeysConstant;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.core.redis.RedisUtil;
import com.fs.common.exception.BaseException;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.bean.BeanUtils;
import com.fs.live.domain.*;
import com.fs.live.mapper.*;
import com.fs.live.param.LiveLotteryProduct;
import com.fs.live.param.LiveReplayParam;
import com.fs.live.service.*;
import com.fs.live.utils.ProcessManager;
import com.fs.live.vo.*;
import com.fs.store.domain.FsMiniprogramSubNotifyTask;
import com.fs.store.domain.FsUser;
import com.fs.store.dto.TemplateMessageSendRequestDTO;
import com.fs.store.enums.MiniAppNotifyTaskStatusEnum;
import com.fs.store.mapper.FsMiniprogramSubNotifyTaskMapper;
import com.fs.store.mapper.FsUserMapper;
import com.fs.system.domain.SysConfig;
import com.fs.system.service.ISysConfigService;
import com.hc.openapi.tool.codec.DigestUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fs.common.utils.sign.Md5Utils;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 直播Service业务层处理
 *
 * @author fs
 * @date 2025-01-17
 */
@Service
@AllArgsConstructor
@Slf4j
public class LiveServiceImpl implements ILiveService
{

    private final ILiveVideoService liveVideoService;
    private final ILiveDataService liveDataService;

    @Autowired
    private ISysConfigService sysConfigService;


    @Autowired
    private ProcessManager processManager;

    @Autowired
    private ILiveGoodsService liveGoodsService;

    @Autowired
    private ILiveRedConfService liveRedConfService;

    @Autowired
    private ILiveLotteryConfService liveLotteryConfService;

    @Autowired
    private ILiveAutoTaskService liveAutoTaskService;
    @Autowired
    private LiveLotteryProductConfMapper liveLotteryProductConfMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private LiveMapper baseMapper;
    @Autowired
    private FsMiniprogramSubNotifyTaskMapper fsMiniprogramSubNotifyTaskMapper;
    @Autowired
    private LiveCouponIssueMapper liveCouponIssueMapper;
    @Autowired
    private FsUserMapper fsUserMapper;

    @Autowired
    private RedisUtil redisUtil;
    /**
     * 查询直播
     *
     * @param liveId 直播主键
     * @return 直播
     */
    @Override
    public Live selectLiveByLiveId(Long liveId){
        Live byId = baseMapper.selectLiveByLiveId(liveId);
        List<LiveVideo> videos = liveVideoService.listByLiveId(liveId, 1);
        if(!videos.isEmpty()){
            LiveVideo liveVideo = videos.get(0);
            byId.setVideoUrl(liveVideo.getVideoUrl());
            byId.setDuration(liveVideo.getDuration());
            byId.setVideoId(liveVideo.getVideoId());
            byId.setVideoType(liveVideo.getVideoType());
        }
        return byId;
    }

    @Override
    public LiveConfigVo currentActivities(Long liveId) {
        LiveGoodsVo liveGoodsVo = liveGoodsService.showGoods(liveId);
        List<LiveRedConf> liveRedConfs = liveRedConfService.selectActivedRed(liveId);
        List<LiveLotteryConfVo> liveLotteryConfs = liveLotteryConfService.selectActivedLottery(liveId);
        List<Long> lotteryIds = liveLotteryConfs.stream().map(LiveLotteryConfVo::getLotteryId).collect(Collectors.toList());
        if (!lotteryIds.isEmpty()) {
            List<LiveLotteryProductListVo> products = liveLotteryProductConfMapper.selectLiveLotteryProductConfByLotteryIds(lotteryIds);
            for (LiveLotteryConfVo liveLotteryConf : liveLotteryConfs) {
                liveLotteryConf.setProducts(products.stream().filter(product -> product.getLotteryId().equals(liveLotteryConf.getLotteryId())).collect(Collectors.toList()));
            }
        }
        return LiveConfigVo.builder().liveRedConfs(liveRedConfs).liveLotteryConfs(liveLotteryConfs).liveGoodsVo(liveGoodsVo).build();
    }

    @Override
    public List<Live> selectNoEndLiveList() {
        return baseMapper.selectNoEndLiveList();
    }

    @Override
    public void updateBatchById(List<Live> list) {
        baseMapper.updateLiveList(list);
    }

    @Override
    public void updateStatusAndTimeBatchById(List<Live> list) {
        baseMapper.updateStatusAndTimeBatchById(list);
    }

    @Override
    public List<Live> asyncToCache() {
        // 同步直播间数据到缓存
        List<Live> list = liveList();
        log.info("开始同步直播间数据到缓存，共{}条数据", list.size());
        ThreadUtil.execute(()->{
            // 清空原有的 ZSet 数据
            redisUtil.delete(LiveKeysConstant.LIVE_HOME_PAGE_LIST);
            for (Live live : list) {
                redisUtil.zSetAdd(LiveKeysConstant.LIVE_HOME_PAGE_LIST, JSON.toJSONString(live), live.getCreateTime().getTime());
                redisUtil.expire(LiveKeysConstant.LIVE_HOME_PAGE_LIST, LiveKeysConstant.LIVE_HOME_PAGE_LIST_EXPIRE, TimeUnit.SECONDS);
            }
            log.info("直播间数据同步到缓存完成");
        });
        return list;
    }

    @Override
    public LiveVo asyncToCacheLiveDetail(Long id) {
        LocalDateTime now = LocalDateTime.now();
		Live live = selectLiveByLiveId(id);
		if(ObjectUtil.isEmpty(live)) {
            return null;
        }
		// Long storeId = liveGoodsService.getStoreIdByLiveId(live.getLiveId());
		LiveVo liveVo = new LiveVo();
        // liveVo.setStoreId(storeId);
		BeanUtils.copyProperties(live, liveVo);
		liveVo.setNowDuration(200L);
        LiveVideo liveVideo = liveVideoService.selectLiveVideoByLiveIdAndType(id, 3);
        if (liveVideo != null) {
            liveVo.setPreviewUrl(liveVideo.getVideoUrl());
            liveVo.setPreviewVideoType(liveVideo.getVideoType());
            liveVo.setPreviewVideoId(liveVideo.getVideoId());
        }
		if(live.getStatus() == 2){
			long seconds = live.getStartTime().until(now, ChronoUnit.SECONDS);
			liveVo.setNowDuration(seconds);
		}
        ThreadUtil.execute(()->{
            log.info("同步直播间详情数据到缓存{}", id);
            redisUtil.delete(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, live.getLiveId()));
            redisUtil.set(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, live.getLiveId()), liveVo,LiveKeysConstant.LIVE_HOME_PAGE_DETAIL_EXPIRE, TimeUnit.SECONDS);
            log.info("直播间数据同步到缓存完成");
        });

        return liveVo;
    }

    @Override
    public LiveConfigVo asyncToCacheLiveConfig(Long liveId) {
        LiveConfigVo liveConfigVo = currentActivities(liveId);
        ThreadUtil.execute(()->{
            log.info("同步配置信息到缓存{}", liveConfigVo);
            redisUtil.delete(String.format(LiveKeysConstant.LIVE_HOME_PAGE_CONFIG, liveId,liveId));
            redisUtil.set(String.format(LiveKeysConstant.LIVE_HOME_PAGE_DETAIL, liveId), liveConfigVo,LiveKeysConstant.LIVE_HOME_PAGE_CONFIG_EXPIRE, TimeUnit.SECONDS);
            log.info("直播间数据同步到缓存完成");
        });
        return liveConfigVo;
    }

    @Override
    public List<Live> liveCompanyList(Long companyId) {
        return baseMapper.liveCompanyList(companyId);
    }

    @Override
    public R subNotifyLive(HashMap<String, Object> param) {
        FsMiniprogramSubNotifyTask notifyTask = new FsMiniprogramSubNotifyTask();
        notifyTask.setPage("/pages_course/living?liveId=" + param.get("liveId"));
        notifyTask.setTaskName("直播间预约提醒");
        notifyTask.setTemplateId((String) param.get("templateId"));
        FsUser fsUser = fsUserMapper.selectFsUserById(Long.valueOf((Integer) param.get("userId")));
        String maOpenId = fsUser.getMaOpenId();
        notifyTask.setTouser(maOpenId);
        notifyTask.setPage(String.valueOf(1));

        notifyTask.setCreateTime(LocalDateTime.now());
        // 状态等待执行
        notifyTask.setStatus(MiniAppNotifyTaskStatusEnum.WAITING.getValue());
        notifyTask.setRetryCount(0);
        notifyTask.setMaxRetries(3);
        Map<String, TemplateMessageSendRequestDTO.TemplateDataValue> data = new HashMap<>();
        HashMap<String,String> mapData = (HashMap<String, String>) param.get("data");
        // 定义日期时间格式器，注意与字符串格式完全匹配
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        notifyTask.setUpdateTime(LocalDateTime.parse(mapData.get("date7"), formatter).minusSeconds(5));
        mapData.forEach((k,v)->{
            TemplateMessageSendRequestDTO.TemplateDataValue dataValue = new TemplateMessageSendRequestDTO.TemplateDataValue();
            dataValue.setValue(mapData.get(k));
            data.put(k, dataValue);
        });
        notifyTask.setData(JSON.toJSONString(data));
//        return R.ok("success");
        fsMiniprogramSubNotifyTaskMapper.insert(notifyTask);

        return R.ok("success");
    }

    @Override
    public Integer updateLiveIsAudit(Live live) {
        return baseMapper.updateLiveIsAudit(live);
    }



    /**
     * 查询企业直播
     * @param liveId            直播ID
     * @param companyId         企业ID
     * @param companyUserId     企业用户ID
     * @return Live
     */
    @Override
    public Live selectLiveByLiveIdAndCompanyIdAndCompanyUserId(Long liveId, Long companyId, Long companyUserId){
//        Live byId = baseMapper.selectLiveByLiveIdAndCompanyIdAndCompanyUserId(liveId, companyId, companyUserId);
        Live byId = baseMapper.selectLiveByLiveIdAndCompanyId(liveId, companyId);
        List<LiveVideo> videos = liveVideoService.listByLiveId(liveId, 1);
        if(!videos.isEmpty()){
            LiveVideo liveVideo = videos.get(0);
            byId.setVideoUrl(liveVideo.getVideoUrl());
            byId.setDuration(liveVideo.getDuration());
        }
        return byId;
    }

    /**
     * 查询直播列表
     *
     * @param live 直播
     * @return 直播
     */
    @Override
    public List<Live> selectLiveList(Live live)
    {
        return baseMapper.selectLiveList(live);
    }


    /**
     * 查询直播列表
     *
     * @param
     * @return 直播
     */
    @Override
    public List<Live> selectLiveToStudent(String liveName,String status,String startTime,String finishTime)
    {
        return baseMapper.selectLiveToStudent(liveName,status,startTime,finishTime);
    }

    /**
     * 新增直播
     *
     * @param live 直播
     * @return 结果
     */
    @Override
    public int insertLive(Live live){


        if(live.getLiveType() == 2 && StringUtils.isEmpty(live.getVideoUrl())) {
            throw new BaseException("录播必须上传视屏");
        }
        live.setCreateTime(DateUtils.getNowDate());
        live.setIsDel(0);
        live.setIsAudit(0);
        live.setStartTime(live.getStartTime().withSecond(1));
        live.setStatus(1);
        int save = baseMapper.insertLive(live);
        // 录播 才有视频
        LiveVideo liveVideo = new LiveVideo();
        liveVideo.setLiveId(live.getLiveId());
        liveVideo.setVideoUrl(live.getVideoUrl());
        liveVideo.setVideoType(1);
        liveVideo.setDuration(live.getDuration());
        liveVideo.setFileSize(live.getFileSize());
        liveVideoService.insertLiveVideo(liveVideo);

        //新增直播数据表
        LiveData liveData = new LiveData();
        liveData.setLiveId(live.getLiveId());
        liveData.setPageViews(0L);
        liveData.setUniqueVisitors(0L);
        liveData.setTotalViews(0L);
        liveData.setUniqueViewers(0L);
        liveData.setPeakConcurrentViewers(0L);
        liveData.setLikes(0L);
        liveData.setFavouriteNum(0L);
        liveData.setFollowNum(0L);
        liveDataService.insertLiveData(liveData);
        return save > 0 ? 1 : 0;
    }

    @Override
    @Transactional
    public int updateLiveEntity(Live live) {
        return baseMapper.updateLive( live);
    }

    /**
     * 修改直播
     *
     * @param live 直播
     * @return 结果
     */
    @Override
    public int updateLive(Live live){
        live.setUpdateTime(DateUtils.getNowDate());
        List<LiveVideo> videos = liveVideoService.listByLiveId(live.getLiveId(), 1);
        if(!videos.isEmpty()){
            LiveVideo liveVideo = videos.get(0);
            liveVideo.setVideoUrl(live.getVideoUrl());
            liveVideo.setUpdateTime(DateUtils.getNowDate());
            liveVideo.setDuration(live.getDuration());
            liveVideo.setFileSize(live.getFileSize());
            liveVideoService.updateLiveVideo(liveVideo);
        }
        if (StringUtils.isNotEmpty(live.getLiveConfig())) {
            LiveReplayParam liveReplayParam = JSON.parseObject(live.getLiveConfig(), LiveReplayParam.class);
            if (liveReplayParam.getIsPlaybackOpen()) {
                liveReplayParam.setStartTime(live.getFinishTime());
                if ("permanent".equals(liveReplayParam.getValidityType())) {
                    liveReplayParam.setFinishTime(null);
                } else if ("days".equals(liveReplayParam.getValidityType())) {
                    liveReplayParam.setFinishTime(live.getFinishTime().plusDays(liveReplayParam.getValidDays()));
                }
                live.setLiveType(3);
                live.setStatus(4);
            } else {
                live.setLiveType(1);
                live.setStatus(3);
            }
            live.setLiveConfig(JSON.toJSONString(liveReplayParam));

        }
        int result = baseMapper.updateLive(live);
        liveAutoTaskService.recalcLiveAutoTask(live);
        return result;
    }

    /**
     * 批量删除直播
     *
     * @param liveIds 需要删除的直播主键
     * @return 结果
     */
    @Override
    public int deleteLiveByLiveIds(Long[] liveIds){
        return baseMapper.deleteLiveByLiveIds(liveIds);
    }

    /**
     * 删除直播信息
     *
     * @param liveId 直播主键
     * @return 结果
     */
    @Override
    public int deleteLiveByLiveId(Long liveId)
    {
        return baseMapper.deleteLiveByLiveId(liveId);
    }

    @Override
    public List<Live> liveList() {
        List<Live> livesList = baseMapper.liveList();
        try {
            // 查询准备开播的直播间
            livesList.addAll(baseMapper.selectReadyStartLiveList());
        }catch (Exception e){
            log.error("查询准备开播的直播间异常", e);
        }
        return livesList;
    }

    @Override
    public R createLiveRoom(Long liveId) {
        Live live = this.selectLiveByLiveId(liveId);
        if (live == null) {
            return R.error("直播不存在");
        }

        if(live.getStatus() == 2){
            return R.ok().put("rtmpUrl", live.getRtmpUrl());
        }
        if (live.getIsAudit() != 1) {
            return R.error("您未通过审核");
        }
        if (live.getIsShow() != 1) {
            return R.error("您未拥有直播权限");
        }
        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("living.config");
        Map<String, String> livingConfigMap = JSON.parseObject(sysConfig.getConfigValue(), Map.class);
        if (livingConfigMap == null || livingConfigMap.isEmpty()) {
            return R.error("缺失直播配置");
        }
        String rtmpPushUrl = generateRtmpPushUrl(livingConfigMap.get("domain"), livingConfigMap.get("app"), liveId.toString());
        String hlvPlayUrl = generateHlvPlayUrl(livingConfigMap.get("http"), livingConfigMap.get("app"), liveId.toString());
        live.setRtmpUrl(rtmpPushUrl);
        live.setFlvHlsUrl(hlvPlayUrl);
        live.setStartTime(LocalDateTime.now());
        live.setStatus(2);
        live.setLiveType(1);
        this.updateLive(live);
        LiveData liveData = new LiveData();
        liveData.setLiveId(liveId);
        liveData.setPageViews(0L);
        liveData.setUniqueVisitors(0L);
        liveData.setTotalViews(0L);
        liveData.setUniqueViewers(0L);
        liveData.setPeakConcurrentViewers(0L);
        liveData.setLikes(0L);
        liveData.setFavouriteNum(0L);
        liveData.setFollowNum(0L);
        liveDataService.insertLiveData(liveData);

        return R.ok().put("rtmpUrl", rtmpPushUrl);
    }

    @Override
    public R getLiveRoom(String liveId) {
        Live live = this.selectLiveByLiveId(Long.valueOf(liveId));
        if (live == null) {
            return R.error("未查询到直播间");
        }
        if (live.getStatus() != 2 && live.getLiveType() == 1) {
            return R.error("直播未开始");
        }
        return R.ok().put("livingUrl", live.getFlvHlsUrl()).put("liveStatus", live.getStatus());
    }

    @Override
    public R checkLiving(Map<String, String> payload) {
        if (payload == null || payload.isEmpty() || !payload.containsKey("userId") || !payload.containsKey("companyId")) {
            return R.error("系统错误，请联系管理员");
        }
        //
//        FsUserTalent fsUserTalent = fsUserTalentService.selectTalentByUserId(payload.get("userId"));
//        if (fsUserTalent == null) {
//            return R.error("您还未成为达人，无法开启直播!");
//        }
//        Live live = baseMapper.selectLiveByUserIdAndCompanyId(String.valueOf(fsUserTalent.getTalentId()), payload.get("companyId"));
        Live live = baseMapper.selectLiveByTalentId("42");
        if (live == null) {
            return R.error("您未拥有直播权限!");
        }
        if (live.getIsAudit() == 0) {
            return R.error("直播间审核中!");
        }


        return R.ok().put("data", live);
    }

    @Override
    public R closeLiving(Map<String, String> payload) {
        if (!payload.containsKey("liveId")) {
            return R.error("直播间id缺失");
        }
        if (!payload.containsKey("userId")) {
            return R.error("关闭直播异常，请联系管理员！");
        }
//        FsUserTalent fsUserTalent = fsUserTalentService.selectTalentByUserId(payload.get("userId"));
        //
        Live live = baseMapper.selectLiveByTalentId("42");
        live.setStatus(1);
        live.setFinishTime(LocalDateTime.now());
        live.setLiveType(2);
        baseMapper.updateLive(live);
        return R.ok();
    }
    /**
     * 循环播放
     * @param live 直播
     * @return R
     */
    @Override
    public R startLoopPlay(Live live) {
        try {
            Live curLive = baseMapper.selectLiveByLiveId(live.getLiveId());
            if (curLive == null) {
                return R.error("直播间不存在");
            }
            LiveVideo curLiveVideo = liveVideoService.selectLiveVideoByLiveId(live.getLiveId());
            if (curLiveVideo == null) {
                return R.error("录播不存在");
            }
            Date now = new Date();

            // 生成唯一的流密钥
            String streamKey = "stream_" + live.getLiveId() + "_" + System.currentTimeMillis();

            // 构建FFmpeg推流命令
            String ffmpegCmd = buildFFmpegCommand(curLiveVideo.getVideoUrl(), streamKey);

            // 启动推流进程
            Process process = processManager.startProcess(ffmpegCmd);

            // 保存流信息到数据库
            curLive.setLiveType(2);
            curLive.setRtmpUrl("rtmp://your-srs-server/live/" + streamKey);
            curLive.setUpdateTime(now);


            baseMapper.updateLive(curLive);

            return R.ok();
        } catch (Exception e) {
            return R.error("启动推流失败: " + e.getMessage());
        }
    }
    /**
     * 停止循环播放
     * @param live 直播
     * @return R
     */
    @Override
    public R stopLoopPlay(Live live) {
        try {
            Live curLive = baseMapper.selectLiveByLiveId(live.getLiveId());
            if (curLive == null) {
                return R.error("直播间不存在");
            }
            // 停止推流进程
            boolean stopped = processManager.stopProcess(curLive.getRemark());
            if (!stopped) {
                return R.error("停止播放失败");
            }
            // 更新流状态
            curLive.setStatus(2);
            curLive.setUpdateTime(new Date());
            baseMapper.updateLive(curLive);

            return R.ok();
        } catch (Exception e) {
            return R.error("停止播放失败: " + e.getMessage());
        }
    }

    @Override
    public R handleShelfOrUn(LiveListVo listVo) {
        int updatedCount = baseMapper.updateBatchLiveList(listVo);
        if (updatedCount > 0) {
            return R.ok("操作成功");
        }
        return R.error();
    }

    @Override
    public R handleDeleteSelected(LiveListVo listVo) {
        int deleteCount = baseMapper.deleteBatchLiveList(listVo);
        if (deleteCount > 0) {
            return R.ok("操作成功");
        }
        return R.error();
    }

    @Override
    public R finishLive(Live live) {
        Live exist = baseMapper.selectLiveByLiveId(live.getLiveId());
        if (exist == null) {
            return R.error("直播间不存在");
        }
        if (exist.getStatus() == 3) {
            return R.error("直播已结束");
        }

        exist.setStatus(3);
        exist.setFinishTime(LocalDateTime.now());
        exist.setUpdateTime(new Date());

        baseMapper.updateLive(exist);

        return R.ok();
    }

    @Override
    public R startLive(Live live) {
        Live exist = baseMapper.selectLiveByLiveId(live.getLiveId());
        if (exist == null) {
            return R.error("直播间不存在");
        }
        if (exist.getStatus() == 2) {
            return R.error("直播已开始");
        }
        if (exist.getIsAudit() != 1) {
            return R.error("您未通过审核");
        }
        if (exist.getIsShow() != 1) {
            return R.error("直播已下架");
        }
        String rtmpPushUrl = generateRtmpPushUrl("rtmp://200149.push.tlivecloud.com", "live", exist.getLiveId().toString());
        String hlvPlayUrl = generateHlvPlayUrl("https://live.test.ifeiyu100.com", "live", exist.getLiveId().toString());
        Date now = new Date();
        exist.setRtmpUrl(rtmpPushUrl);
        exist.setFlvHlsUrl(hlvPlayUrl);

        exist.setStatus(2);
        exist.setUpdateTime(now);
        exist.setFinishTime( null);
        exist.setStartTime(LocalDateTime.now());
        baseMapper.updateLive(exist);


        return R.ok();
    }

    @Override
    public R handleShelfOrUnAdmin(LiveListVo listVo) {
        baseMapper.handleShelfOrUnAdmin(listVo);
        return R.ok();
    }

    @Override
    public R handleDeleteSelectedAdmin(LiveListVo listVo) {
        baseMapper.handleDeleteSelectedAdmin(listVo);
        return R.ok();
    }

    @Override
    @Transactional
    public R copyLive(Live live) {
        Long existLiveId = live.getLiveId();
        Date now = new Date();
        Live exist = baseMapper.selectLiveByLiveId(existLiveId);
        if (exist == null) {
            return R.error("直播间不存在");
        }
        // 复制直播间， 创建 livedata
        // 身份认证
        Live liveEntity = new Live();
        BeanUtils.copyBeanProp(liveEntity, exist);
        liveEntity.setLiveId(null);
        liveEntity.setCompanyId(live.getCompanyId());
        liveEntity.setCompanyUserId(live.getCompanyUserId());
        liveEntity.setRtmpUrl( null);
        liveEntity.setFlvHlsUrl( null);
        liveEntity.setFinishTime( null);
        liveEntity.setIsAudit( 0);
        liveEntity.setStatus( 1);
        liveEntity.setCreateTime( now);
        baseMapper.insertLive(liveEntity);
        if(liveEntity.getLiveId() == null) throw new RuntimeException("插入直播间异常");
        Long newLiveId = liveEntity.getLiveId();
        LiveData liveData = new LiveData();
        liveData.setLiveId(newLiveId);
        liveData.setPageViews(0L);
        liveData.setUniqueVisitors(0L);
        liveData.setTotalViews(0L);
        liveData.setUniqueViewers(0L);
        liveData.setPeakConcurrentViewers(0L);
        liveData.setLikes(0L);
        liveData.setFavouriteNum(0L);
        liveData.setFollowNum(0L);
        liveDataService.insertLiveData(liveData);
        // 优惠券
        List<LiveCouponIssueRelation> liveCouponIssueRelations = liveCouponIssueMapper.selectRelationByLiveId(existLiveId);
        Map<Long, LiveCouponIssueRelation> collect = liveCouponIssueRelations.stream().collect(Collectors.toMap(LiveCouponIssueRelation::getGoodsId, Function.identity(), (existing, replacement) -> existing));
        // 直播视频
        List<LiveVideo> liveVideos = liveVideoService.selectLiveVideosByLiveId(existLiveId);
        if (!liveVideos.isEmpty()) {
            for (LiveVideo liveVideo : liveVideos) {
                LiveVideo videoEntity = new LiveVideo();
                BeanUtils.copyBeanProp(videoEntity, liveVideo);
                videoEntity.setVideoId(null);
                videoEntity.setLiveId(newLiveId);
                videoEntity.setCreateTime(now);
                liveVideoService.insertLiveVideo(videoEntity);
            }
        }

        // 运营自动化
        List<LiveAutoTask> liveAutoTasksList = liveAutoTaskService.selectLiveAutoTaskByLiveId(existLiveId);
        List<LiveAutoTask> barrageTask = liveAutoTasksList.stream().filter(liveAutoTask -> liveAutoTask.getTaskType() == 3L).collect(Collectors.toList());
        List<LiveAutoTask> goodsTask = liveAutoTasksList.stream().filter(liveAutoTask -> liveAutoTask.getTaskType() == 1L).collect(Collectors.toList());
        Map<Long, LiveAutoTask> redMap = liveAutoTasksList.stream()
                .filter(liveAutoTask -> liveAutoTask.getTaskType() == 2L)
                .collect(Collectors.toMap(liveAutoTask -> {
                    return parseIdFromContent(liveAutoTask.getContent(),"redId");
                        }, liveAutoTask -> liveAutoTask, (existing, replacement) -> replacement
                ));
        Map<Long, LiveAutoTask> lotteryMap = liveAutoTasksList.stream()
                .filter(liveAutoTask -> liveAutoTask.getTaskType() == 4L)
                .collect(Collectors.toMap(liveAutoTask -> {
                    return parseIdFromContent(liveAutoTask.getContent(),"lotteryId");
                        }, liveAutoTask -> liveAutoTask, (existing, replacement) -> replacement
                ));
        if (!goodsTask.isEmpty()) {
            LiveAutoTask liveAutoTaskEntity = new LiveAutoTask();
            for (LiveAutoTask liveAutoTask : goodsTask) {
                BeanUtils.copyBeanProp(liveAutoTaskEntity, liveAutoTask);
                liveAutoTaskEntity.setId(null);
                liveAutoTaskEntity.setLiveId(newLiveId);
                liveAutoTaskEntity.setCreateTime(now);
                liveAutoTaskEntity.setUpdateTime(now);
                liveAutoTaskEntity.setFinishStatus(0L);
                liveAutoTaskService.copyInsertLiveAutoTask(liveAutoTaskEntity,liveEntity);
            }
        }
        if (!barrageTask.isEmpty()) {
            LiveAutoTask liveAutoTaskEntity = new LiveAutoTask();
            for (LiveAutoTask liveAutoTask : barrageTask) {
                BeanUtils.copyBeanProp(liveAutoTaskEntity, liveAutoTask);
                liveAutoTaskEntity.setId(null);
                liveAutoTaskEntity.setLiveId(newLiveId);
                liveAutoTaskEntity.setCreateTime(now);
                liveAutoTaskEntity.setUpdateTime(now);
                liveAutoTaskEntity.setFinishStatus(0L);
                liveAutoTaskService.copyInsertLiveAutoTask(liveAutoTaskEntity,liveEntity);
            }
        }
        //直播间红包配置
        List<LiveRedConf> liveRedConfs = liveRedConfService.selectByLiveId(existLiveId);
        if (!liveRedConfs.isEmpty()) {
            LiveRedConf liveRedConfEntity = new LiveRedConf();
            for (LiveRedConf liveRedConf : liveRedConfs) {
                BeanUtils.copyBeanProp(liveRedConfEntity, liveRedConf);
                liveRedConfEntity.setRedId(null);
                liveRedConfEntity.setLiveId(newLiveId);
                liveRedConfEntity.setRedStatus(0L);
                liveRedConfEntity.setCreateTime(now);
                liveRedConfEntity.setTotalSend(0L);
                liveRedConfService.insertLiveRedConf(liveRedConfEntity);
                if (redMap.containsKey(liveRedConf.getRedId())) {
                    LiveAutoTask liveAutoTaskEntity = new LiveAutoTask();
                    LiveAutoTask liveAutoTask = redMap.get(liveRedConf.getRedId());
                    BeanUtils.copyBeanProp(liveAutoTaskEntity, liveAutoTask);
                    liveAutoTaskEntity.setId(null);
                    liveAutoTaskEntity.setLiveId(newLiveId);
                    liveAutoTaskEntity.setCreateTime(now);
                    liveAutoTaskEntity.setUpdateTime(now);
                    liveAutoTaskEntity.setFinishStatus(0L);
                    liveAutoTaskEntity.setContent(JSON.toJSONString(liveRedConfEntity));
                    liveAutoTaskService.copyInsertLiveAutoTask(liveAutoTaskEntity,liveEntity);
                }
            }
        }
        // 直播间礼物配置
        List<LiveLotteryConf> liveLotteryConfs = liveLotteryConfService.selectByLiveId(existLiveId);
        if (!liveLotteryConfs.isEmpty()) {
            LiveLotteryConf liveLotteryConfEntity = new LiveLotteryConf();
            List<Long> lotteryIds = liveLotteryConfs.stream().map(LiveLotteryConf::getLotteryId).collect(Collectors.toList());
            List<LiveLotteryProductConf> products = liveLotteryProductConfMapper.selectEntityByIds(lotteryIds);
            for (LiveLotteryConf liveLotteryConf : liveLotteryConfs) {
                BeanUtils.copyBeanProp(liveLotteryConfEntity, liveLotteryConf);
                liveLotteryConfEntity.setLotteryId(null);
                liveLotteryConfEntity.setLiveId(newLiveId);
                liveLotteryConfEntity.setLotteryStatus(String.valueOf(0));
                liveLotteryConfEntity.setCreateTime(now);
                liveLotteryConfService.insertLiveLotteryConf(liveLotteryConfEntity);
                products.stream().filter(product -> product.getLotteryId().equals(liveLotteryConf.getLotteryId()))
                        .forEach(product -> {
                            product.setId(null);
                            product.setLotteryId(liveLotteryConfEntity.getLotteryId());
                            liveLotteryProductConfMapper.insertLiveLotteryProductConf(product);
                        });
                if (lotteryMap.containsKey(liveLotteryConf.getLotteryId())) {
                    LiveAutoTask liveAutoTaskEntity = new LiveAutoTask();
                    LiveAutoTask liveAutoTask = lotteryMap.get(liveLotteryConf.getLotteryId());
                    BeanUtils.copyBeanProp(liveAutoTaskEntity, liveAutoTask);
                    liveAutoTaskEntity.setId(null);
                    liveAutoTaskEntity.setLiveId(newLiveId);
                    liveAutoTaskEntity.setCreateTime(now);
                    liveAutoTaskEntity.setUpdateTime(now);
                    liveAutoTaskEntity.setFinishStatus(0L);
                    liveAutoTaskEntity.setContent(JSON.toJSONString(liveLotteryConfEntity));
                    liveAutoTaskService.copyInsertLiveAutoTask(liveAutoTaskEntity,liveEntity);
                }
            }
        }
        // 直播间商品
        List<LiveGoods> goodsList = liveGoodsService.selectByLiveId(existLiveId);
        if (!goodsList.isEmpty()) {
            LiveGoods liveGoodsEntity = new LiveGoods();
            for (LiveGoods liveGoods : goodsList) {
                BeanUtils.copyBeanProp(liveGoodsEntity, liveGoods);
                liveGoodsEntity.setGoodsId(null);
                liveGoodsEntity.setLiveId(newLiveId);
                liveGoodsEntity.setCreateTime(now);
                liveGoodsEntity.setCompanyId(live.getCompanyId());
                liveGoodsEntity.setCompanyUserId(live.getCompanyUserId());
                liveGoodsService.insertLiveGoods(liveGoodsEntity);
                if (collect.containsKey(liveGoods.getGoodsId())) {
                    liveCouponIssueRelations.stream().filter(relation -> relation.getGoodsId().equals(liveGoods.getGoodsId())).findFirst().ifPresent(liveCouponIssueRelation -> liveCouponIssueRelation.setGoodsId(liveGoodsEntity.getGoodsId()));
                }
            }
        }
        for (LiveCouponIssueRelation liveCouponIssueRelation : liveCouponIssueRelations) {
            liveCouponIssueRelation.setLiveId(newLiveId);
            liveCouponIssueRelation.setIsShow(0);
            liveCouponIssueMapper.insertLiveCouponIssueRelation(liveCouponIssueRelation);
        }

        return R.ok("复制成功");
    }

    private Long parseIdFromContent(String content, String key) {
        // 假设content是JSON字符串，使用FastJSON解析
        JSONObject jsonObject = JSON.parseObject(content);
        return jsonObject.getLong(key);
    }



    /**
     * 构建FFmpeg推流命令
     */
    private String buildFFmpegCommand(String videoPath, String streamKey) {
        return String.format(
                "ffmpeg -re -stream_loop -1 -i \"%s\" -c:v libx264 -preset ultrafast -b:v 1000k " +
                        "-c:a aac -b:a 128k -f flv rtmp://your-srs-server/live/%s",
                videoPath, streamKey
        );
    }

    /**
     * 身份证信息验证 阿里商品购买接口
     * @param payload
     * @return
     */
    @Override
    public R verifyIdInfo(Map<String, String> payload) {
        if (!payload.containsKey("idCardUrl")) {
            return R.error("身份证信息缺失");
        }
        Live live = baseMapper.selectLiveByLiveId(Long.valueOf(payload.get("liveId")));
        if (live == null) {
            return R.error("直播间不存在");
        }
        String url = "https://idcardside.market.alicloudapi.com/idcard_ocr";
        String appCode = "0a01beb5322e49ca802423fe29df9582";
        try {
            Map<String, String> params = new HashMap<>();
            //image 和 url 二选一 ，选择其中一个时，请注释另外一个参数,默认使用image
            params.put("url", payload.get("idCardUrl"));
//            params.put("image", "data:image/jpeg;base64," + base64String);
            String result = postForm(appCode, url, params);
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (200 == jsonObject.getIntValue("code") && jsonObject.getBooleanValue("success")) {
                live.setIdCardUrl(payload.get("idCardUrl"));
                baseMapper.updateLive(live);
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("身份证信息校验异常");
        }
        return R.error("身份证信息校验失败");
    }

    /** 上面方法的数据解析
     * 用到的HTTP工具包：okhttp 3.13.1
     * <dependency>
     * <groupId>com.squareup.okhttp3</groupId>
     * <artifactId>okhttp</artifactId>
     * <version>3.13.1</version>
     * </dependency>
     */
    public static String postForm(String appCode, String url, Map<String, String> params) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().build();
        FormBody.Builder formbuilder = new FormBody.Builder();
        Iterator<String> it = params.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            formbuilder.add(key, params.get(key));
        }
        FormBody body = formbuilder.build();
        Request request = new Request.Builder().url(url).addHeader("Authorization", "APPCODE " + appCode).post(body).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }


    public static String generateRtmpPushUrl(String domain, String app, String liveId) {
        Date now = new Date();
        now.setTime(now.getTime() + 24 * 3600 * 1000);

        return domain +
                "/" +
                app +
                "/" +
                liveId +
                "?" +
                "txSecret=" +
                Md5Utils.hash("a61df75ae15271d7ef922f308e61e92e" + liveId + to16Hex(now)) +
                "&" +
                "txTime=" +
                to16Hex(now);
    }

    /**
     * 生成 FLV 播放地址（用于前端播放）
     */
    public static String generateHlvPlayUrl(String domain, String app, String liveId) {
        Date now = new Date();
        now.setTime(now.getTime() + 24 * 3600 * 1000);

        return domain +
                "/" +
                app +
                "/" +
                liveId +
                ".flv?" +
                "txSecret=" +
                Md5Utils.hash("NiMfMYG5HQxZQ5bk88ri" + liveId + to16Hex(now)) +
                "&" +
                "txTime=" +
                to16Hex(now);
    }

    /**
     * 将传入的时间转换为 16进制
     *
     * @param date
     * @return
     */
    public static String to16Hex(Date date) {
        Long aLong = date.getTime() / 1000;
        String hexString = Long.toHexString(aLong);
        return hexString.toUpperCase();
    }
}
