package com.fs.course.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fs.common.core.domain.R;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.DictUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.CompanyTag;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyTagMapper;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.course.config.CourseConfig;
import com.fs.course.domain.*;
import com.fs.course.mapper.*;
import com.fs.course.param.*;
import com.fs.course.param.newfs.FsUserCourseListParam;
import com.fs.course.service.IFsUserCourseService;
import com.fs.course.vo.*;
import com.fs.course.vo.newfs.FsUserCourseListVO;
import com.fs.his.vo.OptionsVO;
import com.fs.system.service.ISysConfigService;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.List;

/**
 * 课程Service业务层处理
 *
 * @author fs
 * @date 2024-05-15
 */
@Service
@Slf4j
public class FsUserCourseServiceImpl implements IFsUserCourseService
{
    @Autowired
    private FsUserCourseMapper fsUserCourseMapper;
    @Autowired
    private FsUserCourseCommentMapper fsUserCourseCommentMapper;
    @Autowired
    private FsUserCourseNoteMapper fsUserCourseNoteMapper;
    @Autowired
    private FsUserCourseVideoMapper fsUserCourseVideoMapper;
    @Autowired
    private FsUserCourseStudyMapper fsUserCourseStudyMapper;
    @Autowired
    private FsUserCourseStudyLogMapper fsUserCourseStudyLogMapper;
    @Autowired
    private CompanyTagMapper companyTagMapper;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private FsCourseLinkMapper fsCourseLinkMapper;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private FsCourseWatchLogMapper fsCourseWatchLogMapper;
    @Autowired
    private FsCourseAnswerLogsMapper fsCourseAnswerLogsMapper;

    private static final String realLink = "/courseH5/pages/course/learning?course=";
    private static final String shortLink = "/courseH5/pages/course/learning?s=";
    private static final String userRealLink = "/pages/user/users/becomeVIP?";

    /**
     * 查询课程
     *
     * @param courseId 课程主键
     * @return 课程
     */
    @Override
    public FsUserCourse selectFsUserCourseByCourseId(Long courseId)
    {
        return fsUserCourseMapper.selectFsUserCourseByCourseId(courseId);
    }

    /**
     * 查询课程列表
     *
     * @param fsUserCourse 课程
     * @return 课程
     */
    @Override
    public List<FsUserCourse> selectFsUserCourseList(FsUserCourse fsUserCourse)
    {
        return fsUserCourseMapper.selectFsUserCourseList(fsUserCourse);
    }

    /**
     * 新增课程
     *
     * @param fsUserCourse 课程
     * @return 结果
     */
    @Override
    public int insertFsUserCourse(FsUserCourse fsUserCourse)
    {
        fsUserCourse.setCreateTime(DateUtils.getNowDate());
        return fsUserCourseMapper.insertFsUserCourse(fsUserCourse);
    }

    /**
     * 修改课程
     *
     * @param fsUserCourse 课程
     * @return 结果
     */
    @Override
    public int updateFsUserCourse(FsUserCourse fsUserCourse)
    {
        fsUserCourse.setUpdateTime(DateUtils.getNowDate());
        return fsUserCourseMapper.updateFsUserCourse(fsUserCourse);
    }

    /**
     * 批量删除课程
     *
     * @param courseIds 需要删除的课程主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCourseByCourseIds(Long[] courseIds)
    {
        return fsUserCourseMapper.deleteFsUserCourseByCourseIds(courseIds);
    }

    /**
     * 删除课程信息
     *
     * @param courseId 课程主键
     * @return 结果
     */
    @Override
    public int deleteFsUserCourseByCourseId(Long courseId)
    {
        return fsUserCourseMapper.deleteFsUserCourseByCourseId(courseId);
    }


    @Override
    public FsUserCourseUVO selectFsUserCourseUVOByCourseId(Long courseId) {
        FsUserCourseUVO vo = fsUserCourseMapper.selectFsUserCourseUVOByCourseId(courseId);
        vo.setNoteNum(fsUserCourseNoteMapper.selectFsUserCourseNoteCountByCourseId(courseId));
        vo.setCommentNum(fsUserCourseCommentMapper.selectCommentNumByCourseId(courseId));
        vo.setCommentList(fsUserCourseCommentMapper.selectFsUserCourseCommentListVOByCourseId(courseId));
//        vo.setTalentAvatar("https://cos.his.cdwjyyh.com/fs/20240528/07ed79115eb747a2a6083e2e6a2cbc6b.jpg");
        FsUserCourseListUParam param = new FsUserCourseListUParam();
        param.setCateId(vo.getCateId());
        param.setIsTui(1);
        List<FsUserCourseListUVO> list= fsUserCourseMapper.selectFsUserCourseListUVO(param);
        Iterator<FsUserCourseListUVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            FsUserCourseListUVO course = iterator.next();
            if (course.getCourseId().equals(courseId)) {
                iterator.remove();
            }
        }
        vo.setCourseList(list);
        return vo;
    }


    @Override
    public int updateViews(Long courseId) {
        return fsUserCourseMapper.updateViews(courseId);
    }

    @Override
    public int updateShares(Long courseId) {
        return fsUserCourseMapper.updateShares(courseId);
    }

    @Override
    public int updateLikes(Long courseId, Integer type) {
        if (type == 1){
            return fsUserCourseMapper.addLikes(courseId);
        }else {
            return fsUserCourseMapper.minusLikes(courseId);
        }
    }

    @Override
    public int updateFavorite(Long courseId, Integer type) {
        if (type == 1){
            return fsUserCourseMapper.addFavorite(courseId);
        }else {
            return fsUserCourseMapper.minusFavorite(courseId);
        }
    }

    @Override
    public List<FsUserCourseListUVO> selectFsUserCourseListUVO(FsUserCourseListUParam param) {
        return fsUserCourseMapper.selectFsUserCourseListUVO(param);
    }

    @Override
    public List<FsUserCourseListUVO> selectFsUserCourseCommentListUVO(FsUserCourseListUParam param) {
        return fsUserCourseMapper.selectFsUserCourseCommentListUVO(param);
    }

    @Override
    public List<OptionsVO> selectFsUserCourseAllList() {
        return fsUserCourseMapper.selectFsUserCourseAllList();
    }


    @Override
    public List<FsUserCourseListPVO> selectFsUserCourseListPVO(FsUserCourse param) {
        List<FsUserCourseListPVO> fsUserCourseListPVOS = fsUserCourseMapper.selectFsUserCourseListPVO(param);
        for (FsUserCourseListPVO fsUserCourseListPVO : fsUserCourseListPVOS){
            if(ObjectUtils.isNotNull(fsUserCourseListPVO.getProject())){
                String sysCourseProject = DictUtils.getDictLabel("sys_course_project", String.valueOf(fsUserCourseListPVO.getProject()));
                fsUserCourseListPVO.setProjectName(sysCourseProject);
            }
        }
        return fsUserCourseListPVOS;
    }

    @Override
    public int updateDuration(FsUserCourseAddStudyCourseParam param) {
        return fsUserCourseMapper.updateDuration(param);
    }

    @Override
    public int updateFsUserCourseIsShow(Long[] courseIds, int status) {
        return fsUserCourseMapper.updateFsUserCourseIsShow(courseIds,status);
    }

    @Override
    @Transactional
    public R addStudyCourse(FsUserCourseAddStudyCourseParam param) {
        FsUserCourseVideo courseVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());

        if (courseVideo == null) {
            return R.error("视频不存在");
        }

        FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
        if (course == null) {
            return R.error("课堂不存在");
        }


        FsUserCourseStudyLog log = getOrCreateStudyLog(param, course, courseVideo);

        FsUserCourseStudy courseStudy = fsUserCourseStudyMapper.selectFsUserCourseStudyByAddStudy(param.getUserId(), param.getCourseId());

        if (courseStudy == null) {
            courseStudy = createStudyRecord(param);
            log.setStudyId(courseStudy.getStudyId());
            fsUserCourseStudyLogMapper.insertFsUserCourseStudyLog(log);
        } else {
            log.setStudyId(courseStudy.getStudyId());
            if (log.getLogId() == null) {
                fsUserCourseStudyLogMapper.insertFsUserCourseStudyLog(log);
            } else {
                fsUserCourseStudyLogMapper.updateFsUserCourseStudyLog(log);
            }
        }
        updateDuration(param);
        Long studyCount = fsUserCourseStudyLogMapper.selectStudyLogFinishCount(param.getCourseId(),param.getUserId());
        courseStudy.setPeriodStudy(studyCount);
        if (studyCount.equals(courseStudy.getPeriodTotal())){
            courseStudy.setStatus(3);
        }
        fsUserCourseStudyMapper.updateFsUserCourseStudy(courseStudy);
        return R.ok();
    }

    @Override
    @Transactional
    public R getIntegralByCourseVideo(FsUserCourseGetIntegralParam param) {
//        FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
//        if (video == null) {
//            return R.error("视频不存在");
//        }
//        FsUserCourse course = fsUserCourseMapper.selectFsUserCourseByCourseId(video.getCourseId());
//        if (course==null || course.getIsShow()==0){
//            return R.error("课程不存在");
//        }
//        FsUser user = fsUserMapper.selectFsUserByUserId(param.getUserId());
//        if (user==null){
//            return R.error("用户不存在");
//        }
//        String json =configService.selectConfigByKey("his.integral");
//        IntegralConfig config= JSONUtil.toBean(json,IntegralConfig.class);
//        Integer todayTotalIntegral= fsUserIntegralLogsMapper.selectTodayTotalIntegral(config.getIntegralTypeByOneDay(),param.getUserId());
//        if (todayTotalIntegral==null){
//            todayTotalIntegral=0;
//        }
//        if (todayTotalIntegral>=config.getIntegralByOneDay()){
//            return R.error("当天芳华币已达限额");
//        }
//        int rate = (int)((double)param.getDuration() / video.getDuration() * 100);
//        if (rate>=50){
//            FsUserIntegralLogs integralLogs = fsUserIntegralLogsMapper.selectFsUserIntegralByCourseVideo(param.getVideoId(),param.getUserId());
//            if (integralLogs!=null){
//                return R.error("该用户已获取此小节积分");
//            }
//            FsUser userMap = new FsUser();
//            userMap.setIntegral(user.getIntegral()+config.getIntegralCourse());
//            userMap.setUserId(user.getUserId());
//            fsUserMapper.updateFsUser(userMap);
//            integralLogs = new FsUserIntegralLogs();
//            //写入日志
//            integralLogs.setIntegral(config.getIntegralCourse().longValue());
//            integralLogs.setUserId(param.getUserId());
//            integralLogs.setBalance(userMap.getIntegral());
//            integralLogs.setLogType(10);
//            integralLogs.setBusinessId(video.getVideoId().toString());
//            integralLogs.setCreateTime(new Date());
//            fsUserIntegralLogsMapper.insertFsUserIntegralLogs(integralLogs);
//            return R.ok("恭喜您获得"+config.getIntegralCourse()+"芳华币");
//        }
//        return R.error("观看进度不满百分之五十");
        return null;
    }

    private FsUserCourseStudyLog getOrCreateStudyLog(FsUserCourseAddStudyCourseParam param, FsUserCourse course, FsUserCourseVideo courseVideo) {
        FsUserCourseStudyLog log = fsUserCourseStudyLogMapper.selectFsUserCourseStudyLogByVideo(param.getUserId(), param.getVideoId());
        if (log != null) {
            log.setTotalTimes(log.getTotalTimes()+param.getDuration());
            updateRate(log,param.getDuration(),log.getTimes());
            log.setCreateTime(new Date());
        } else {
            log = new FsUserCourseStudyLog();
            log.setUserId(param.getUserId());
            log.setCourseId(param.getCourseId());
            log.setCourseName(course.getCourseName());
            log.setVideoName(courseVideo.getTitle());
            log.setVideoId(param.getVideoId());
            log.setCurrentTimes(param.getDuration());
            log.setTimes(courseVideo.getDuration());
            log.setCreateTime(new Date());
            log.setTotalTimes(param.getDuration());
            updateRate(log, param.getDuration(), courseVideo.getDuration());
        }
        return log;
    }

    private void updateRate(FsUserCourseStudyLog log, Long currentTimes, Long totalTimes) {
        if (currentTimes <= totalTimes) {
            short rate = (short) ((double) currentTimes / totalTimes * 100);
            log.setRate(rate);
            if (rate>=90){
                log.setStatus(1);
            }
        } else {
            log.setCurrentTimes(totalTimes);
            log.setRate((short) 100);
            log.setStatus(1);
        }
    }

    private FsUserCourseStudy createStudyRecord(FsUserCourseAddStudyCourseParam param) {
        Long videoCount = fsUserCourseVideoMapper.selectVideoCountByCourseId(param.getCourseId());
        FsUserCourseStudy studyMap = new FsUserCourseStudy();
        studyMap.setPeriodTotal(videoCount);
        studyMap.setUserId(param.getUserId());
        studyMap.setCourseId(param.getCourseId());
        studyMap.setCreateTime(new Date());
        studyMap.setStatus(2);
        fsUserCourseStudyMapper.insertFsUserCourseStudy(studyMap);
        return studyMap;
    }

    @Override
    public FsUserCourseVideoH5VO selectFsUserCourseVideoH5VOByVideoId(Long videoId) {
        return fsUserCourseMapper.selectFsUserCourseVideoH5VOByVideoId(videoId);
    }

    @Override
    public FsUserCourseVideoH5DVO selectFsUserCourseVideoH5DVOByVideoId(Long videoId) {
        return fsUserCourseMapper.selectFsUserCourseVideoH5DVOByVideoId(videoId);
    }

    @Override
    public List<FsUserCourseListPVO> selectFsUserCourseListCompanyPVO(FsUserCourseParam fsUserCourse) {
        return fsUserCourseMapper.selectFsUserCourseListCompanyPVO(fsUserCourse);
    }

    @Override
    public List<FsUserCourseListVO> getFsUserCourseList(FsUserCourseListParam param) {
        return fsUserCourseMapper.getFsUserCourseList(param);
    }

    /**
     * 查询用户参与记录
     * @param params 条件
     * @return  list
     */
    @Override
    public List<FsUserCourseParticipationRecordVO> getParticipationRecordByMap(Map<String, Object> params) {
        List<FsUserCourseParticipationRecordVO> list = fsUserCourseMapper.getParticipationRecordByMap(params);
        list.forEach(recordVO -> {
            List<CompanyTag> companyTags = companyTagMapper.selectCompanyTagListByUserId(recordVO.getUserId());
            recordVO.setTags(companyTags);

            Map<String, Object> sumMap = fsCourseWatchLogMapper.selectSumByUserIdAndVideoId(recordVO.getUserId(), recordVO.getVideoId());
            // 观看次数
            recordVO.setWatchCount((Long) sumMap.getOrDefault("watchCount", 0L));

            // 完播次数
            recordVO.setFinishCount((Long) sumMap.getOrDefault("finishCount", 0L));

            // 观看时长
            recordVO.setWatchTime((BigDecimal) sumMap.getOrDefault("watchTime", BigDecimal.ZERO));

            // 领取状态
            Long count = fsCourseAnswerLogsMapper.selectRedStatus(recordVO.getUserId(), recordVO.getVideoId());
            if (Objects.nonNull(count) && count > 0) {
                recordVO.setRedStatus(1);
            } else {
                recordVO.setRedStatus(0);
            }
        });
        return list;
    }

    @Override
    public R createCourseSortLink(FsCourseLinkCreateParam param) {
        String json = configService.selectConfigByKey("h5.course.config");
        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);

        //新增链接表信息
        FsCourseLink link = new FsCourseLink();
        BeanUtils.copyProperties(param, link);
        link.setLinkType(0);
        link.setIsRoom(0);

        FsCourseRealLink courseMap = new FsCourseRealLink();
        BeanUtils.copyProperties(link, courseMap);
        String courseJson = JSON.toJSONString(courseMap);

        link.setRealLink(realLink + courseJson);
        String random = generateRandomString();
        link.setLink(random);
        link.setCreateTime(new Date());

        //获取过期时间
        Calendar calendar = getExpireDay(param, config, link.getCreateTime());
        link.setUpdateTime(calendar.getTime());
        int i = fsCourseLinkMapper.insertFsCourseLink(link);
        if (i > 0){
            String domainName = getDomainName(param.getCompanyUserId(), config);
            String sortLink = domainName + shortLink + link.getLink();
            return R.ok().put("url", sortLink).put("link", random);
        }
        return R.error("生成链接失败！");
    }


    @Override
    public String createCourseImageQR(String url, String backgroundImagePath, InputStream file,
                                      String outputFormat, String title, String duration) throws Exception {
        // 读取并缩放背景图片
        BufferedImage backgroundImage = createScaledBackgroundImage(backgroundImagePath);
        int scaledWidth = backgroundImage.getWidth();
        int scaledHeight = backgroundImage.getHeight();

        // 创建最终的合成图片，确保底部区域有足够空间
        int bottomHeight = 200; // 增加底部区域高度，确保内容完全显示
        int totalHeight = scaledHeight + bottomHeight;
        BufferedImage combined = new BufferedImage(scaledWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = initializeGraphics(combined);

        // 绘制背景和底部白色区域
        graphics.drawImage(backgroundImage, 0, 0, null);
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, scaledHeight, scaledWidth, bottomHeight);

        // 绘制推荐区域（图片和文字）
        drawRecommendationArea(graphics, file, scaledHeight, "云联融智", "为您推荐");

        // 绘制二维码
        drawQRCode(graphics, url, scaledWidth, totalHeight);

        // 绘制标题和时长
        drawTitleAndDuration(graphics, title, duration, scaledHeight);

        graphics.dispose();

        // 转换为Base64
        return convertToBase64(combined, outputFormat);
    }

    /**
     * 读取并缩放背景图片
     */
    private BufferedImage createScaledBackgroundImage(String backgroundImagePath) throws IOException {
        // 设置固定的目标尺寸
        final int TARGET_WIDTH = 600;
        final int TARGET_HEIGHT = 300; // 固定背景图片高度为300像素

        URL imagePath = new URL(backgroundImagePath);
        BufferedImage originalBackground = ImageIO.read(imagePath);

        // 计算缩放比例，以高度为基准
        double scale = (double) TARGET_HEIGHT / originalBackground.getHeight();
        int scaledWidth = (int) (originalBackground.getWidth() * scale);

        // 创建固定大小的背景图片
        BufferedImage backgroundImage = new BufferedImage(TARGET_WIDTH, TARGET_HEIGHT, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = backgroundImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

        // 计算居中位置
        int x = (TARGET_WIDTH - scaledWidth) / 2;

        // 绘制缩放后的图片
        g2d.drawImage(originalBackground, x, 0, scaledWidth, TARGET_HEIGHT, null);
        g2d.dispose();

        return backgroundImage;
    }

    /**
     * 初始化图形上下文
     */
    private Graphics2D initializeGraphics(BufferedImage combined) {
        Graphics2D graphics = combined.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        return graphics;
    }

    /**
     * 绘制推荐区域
     */
    private void drawRecommendationArea(Graphics2D graphics, InputStream file, int scaledHeight, String recommendName, String recommendContent) throws IOException {
        // 读取并绘制推荐图片
        BufferedImage referenceImg = ImageIO.read(file);
        int refHeight = 40;
        int refWidth = 40;
        int refY = scaledHeight + 20;
        int refX = 30;
        graphics.drawImage(referenceImg, refX, refY, refWidth, refHeight, null);

        // 设置并绘制推荐文字
        Font recommendFont = new Font("微软雅黑", Font.BOLD, 16);
        graphics.setFont(recommendFont);

        // 绘制"云联融智"
        int textX = refX + refWidth + 10;
        int textY = refY + 25;
        graphics.setColor(new Color(51, 51, 51));
        graphics.drawString(recommendName, textX, textY);

        // 绘制"为您推荐"
        FontMetrics metrics = graphics.getFontMetrics(recommendFont);
        int brandWidth = metrics.stringWidth(recommendName);
        int textX1 = textX + brandWidth + 5;
        graphics.setColor(new Color(102, 102, 102));
        graphics.drawString(recommendContent, textX1, textY);
//        FontMetrics metrics = graphics.getFontMetrics(recommendFont);
        int reWidth = metrics.stringWidth(recommendContent);
    }


    /**
     * 生成二维码图片
     */
    private static BufferedImage generateQrCodeImage(String text, int width, int height) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    /**
     * 绘制二维码
     */
    private void drawQRCode(Graphics2D graphics, String url, int scaledWidth, int totalHeight) throws Exception {
        BufferedImage qrCodeImage = generateQrCodeImage(url, 200, 200);
        int qrSize = 100;
        int qrMarginRight = 25;
        int qrMarginBottom = 30;
        int qrX = scaledWidth - qrSize - qrMarginRight;
        int qrY = totalHeight - qrSize - qrMarginBottom;
        graphics.drawImage(qrCodeImage, qrX, qrY, qrSize, qrSize, null);
    }

    /**
     * 绘制标题和时长
     */
    private void drawTitleAndDuration(Graphics2D graphics, String title, String duration, int scaledHeight) {
        Font titleFont = new Font("微软雅黑", Font.BOLD, 18);
        Font descFont = new Font("微软雅黑", Font.PLAIN, 14);

        int contentX = 30;
        int titleY = scaledHeight + 85;
        int descY = titleY + 25;

        graphics.setFont(titleFont);
        graphics.setColor(new Color(51, 51, 51));
        graphics.drawString(title, contentX, titleY);

        graphics.setFont(descFont);
        graphics.setColor(new Color(102, 102, 102));
        if(StringUtils.isNotBlank(duration)){
            // 将秒转化为分钟
            BigDecimal bigDecimal = new BigDecimal(duration);
            bigDecimal = bigDecimal.divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
            String minutes = bigDecimal.toString();
            graphics.drawString("播放时长：" + minutes + "分钟", contentX, descY);
        } else {
            graphics.drawString("播放时长：" + "暂无", contentX, descY);
        }

    }

    /**
     * 将图片转换为Base64字符串
     */
    private String convertToBase64(BufferedImage image, String outputFormat) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, outputFormat, outputStream);
        byte[] imageBytes = outputStream.toByteArray();
        String s = Base64.getEncoder().encodeToString(imageBytes);
        StringBuilder result = new StringBuilder();
        if(StringUtils.isNotEmpty(s)){
            result.append("data:image/png;base64,").append(s);
        }
        return result.toString();
    }

    @Override
    public R createCourseMemberSortLink(FsCourseLinkCreateParam param) {
        // todo 需要调整路径
        String json = configService.selectConfigByKey("company.user");
        JSONObject object = JSON.parseObject(json);
        String realLinkDomainName = object.get("realLinkDomainName").toString();
        Integer linkExpireTime = Integer.parseInt(object.get("linkExpireTime").toString());

        //新增链接表信息
        FsCourseLink link = new FsCourseLink();
        BeanUtils.copyProperties(param, link);
        link.setLinkType(0);
        link.setIsRoom(0);

        FsCourseRealLink courseMap = new FsCourseRealLink();
        BeanUtils.copyProperties(link, courseMap);
        String courseJson = JSON.toJSONString(courseMap);

        link.setRealLink(userRealLink + courseJson);
        link.setLink(generateRandomString());
        link.setCreateTime(new Date());

        //获取过期时间
        CourseConfig config = new CourseConfig();
        config.setRealLinkDomainName(realLinkDomainName);
        config.setVideoLinkExpireDate(linkExpireTime);
        Calendar calendar = getExpireDay(param, config, link.getCreateTime());
        link.setUpdateTime(calendar.getTime());
        int i = fsCourseLinkMapper.insertFsCourseLink(link);
        if (i > 0){
            String domainName = getDomainName(param.getCompanyUserId(), config);
            String sortLink = domainName + shortLink + link.getLink();
            return R.ok().put("url", sortLink);
        }
        return R.error("生成链接失败！");
    }

    @Override
    public InputStream handleImage(String url, String path) throws IOException {
        InputStream inputstream = null;
        if(StringUtils.isNotEmpty(url)){
            URL newUrl = new URL(url);
            URLConnection connection = newUrl.openConnection();
            // 设置用户代理，避免被服务器拒绝
            connection.setRequestProperty("User-Agent", "Mozilla/5.0");
            inputstream = connection.getInputStream();
        } else {
            File file = new File(path);
            try{
                inputstream = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                log.error("获取本地路径失败：{}", path);
            }
        }
        log.info("头像/logo路径, url:{}, path：{}", url, path);
        return inputstream;
    }

    @Override
    public String createUserImageQR(String url, String backgroundImagePath, InputStream file, String outputFormat, Long companyUserId) throws Exception {
        // 读取并缩放背景图片
        BufferedImage backgroundImage = createScaledBackgroundImage(backgroundImagePath);
        int scaledWidth = backgroundImage.getWidth();
        int scaledHeight = backgroundImage.getHeight();

        // 创建最终的合成图片，确保底部区域有足够空间
        int bottomHeight = 200; // 增加底部区域高度，确保内容完全显示
        int totalHeight = scaledHeight + bottomHeight;
        BufferedImage combined = new BufferedImage(scaledWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = initializeGraphics(combined);

        // 绘制背景和底部白色区域
        graphics.drawImage(backgroundImage, 0, 0, null);
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, scaledHeight, scaledWidth, bottomHeight);

        //获取销售名称
        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(companyUserId);

        // 绘制推荐区域（图片和文字）
        drawRecommendationArea(graphics, file, scaledHeight, companyUser != null ? companyUser.getNickName(): "云联融智", "邀请您成为会员");

        // 绘制二维码
        drawQRCode(graphics, url, scaledWidth, totalHeight);

        graphics.dispose();

        // 转换为Base64
        return convertToBase64(combined, outputFormat);
    }

    @Override
    public List<FsCourseListBySidebarVO> getFsCourseListBySidebar(FsCourseListBySidebarParam param) {
        return  fsUserCourseMapper.getFsCourseListBySidebar(param);
    }

    private static Calendar getExpireDay(FsCourseLinkCreateParam param, CourseConfig config, Date createTime) {
        Integer expireDuration;
        if (param.getEffectiveDuration() == null || param.getEffectiveDuration() == 0){
            expireDuration = config.getVideoLinkExpireDate();
        }else {
            expireDuration = param.getEffectiveDuration();
        }
        // 设置过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(createTime);
        calendar.add(Calendar.MINUTE, expireDuration);
        return calendar;
    }


    //

    /**
     * 生成随机的八位数字字母大小写的字符串（改为生成随机不重复的雪花id）
     */
    public static String generateRandomString() {
        return FsCourseLinkServiceImpl.generateRandomString();
    }

    private String getDomainName(Long companyUserId, CourseConfig config){
        String domainName = companyUserMapper.selectDomainByUserId(companyUserId);
        if (StringUtils.isEmpty(domainName)){
            domainName = config.getRealLinkDomainName();
        }
        return domainName;
    }
}
