package com.fs.app.controller.store;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.fs.app.annotation.Login;
import com.fs.app.controller.AppBaseController;
import com.fs.common.OrderUtils;
import com.fs.common.config.FSConfig;
import com.fs.common.core.domain.R;
import com.fs.common.core.domain.ResponseResult;
import com.fs.common.exception.CustomException;
import com.fs.common.param.BaseQueryParam;
import com.fs.core.config.WxMaConfiguration;
import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
import com.fs.course.service.IFsUserCourseVideoService;
import com.fs.hisStore.domain.FsStoreOrderScrm;
import com.fs.hisStore.domain.FsUserBillScrm;
import com.fs.hisStore.domain.FsUserPromoterApplyScrm;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.param.*;
import com.fs.hisStore.service.*;
import com.fs.hisStore.vo.FsStoreOrderTuiVO;
import com.fs.hisStore.vo.FsStoreProductRelationQueryVO;
import com.fs.hisStore.vo.FsUserExtractVO;
import com.fs.hisStore.vo.FsUserTuiVO;
import com.fs.utils.FileCacheService;
import com.fs.wx.miniapp.config.WxMaProperties;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;


@Api("个人中心")
@RestController
@RequestMapping(value="/store/app/user")
@Slf4j
public class UserScrmController extends AppBaseController {

    @Autowired
    private FSConfig fsConfig;
    @Autowired
    private IFsUserScrmService userService;
    @Autowired
    private IFsStoreOrderScrmService orderService;
    @Autowired
    private IFsUserBillScrmService userBillService;
    @Autowired
    private IFsStoreProductRelationScrmService productRelationService;

    @Autowired
    private IFsUserExtractScrmService userExtractService;
    @Autowired
    private IFsUserPromoterApplyScrmService userPromoterApplyService;
    @Autowired
    private IFsUserCourseVideoService courseVideoService;
    @Autowired
    private IFsUserScrmService fsUserService;
    @Autowired
    private FileCacheService fileCacheService;
    @Autowired
    private WxMaProperties maProperties;
    /**
     * 获取用户信息
     * @param request
     * @return     */
    @Login
    @ApiOperation("获取用户信息")
    @GetMapping("/getUserInfo")
    public R getUserInfo(HttpServletRequest request){
        try {
            FsUserScrm user=userService.selectFsUserById(Long.parseLong(getUserId()));
            if (user.getIsShow() !=null && user.getIsShow() == 0){
                FsStoreOrderScrm order = orderService.selectOrderByUserIdLimit1(user.getUserId());
                if (order!=null){
                    user.setIsShow(1);
                }
            }
            return R.ok().put("user",user);
        } catch (Exception e){
            log.error("【获取用户信息】：{}",e);
            return R.error("操作异常");
        }
    }


    @Login
    @ApiOperation("判断用户是否存在头像昵称")
    @GetMapping("/checkUserInfo")
    public R checkUserInfo(){
        log.info("【判断判断用户是否存在头像昵称】：{}",getUserId());
        return courseVideoService.checkUserInfo(Long.parseLong(getUserId()));
    }

    @Login
    @ApiOperation("检测是否登录")
    @GetMapping("/checkLogin")
    public R checkLogin(HttpServletRequest request){
        return R.ok("认证成功");
    }

    @Login
    @ApiOperation("获取推荐海报")
    @GetMapping("/getTuiImgOld")
    public R getTuiImgOld(HttpServletRequest request){
        try {
            FsUserScrm user=userService.selectFsUserById(Long.parseLong(getUserId()));
            if(StringUtils.isEmpty(user.getUserCode())){
                FsUserScrm userMap=new FsUserScrm();
                userMap.setUserId(user.getUserId());
                userMap.setUserCode(OrderUtils.genUserCode());
                userService.updateFsUser(userMap);
                user.setUserCode(userMap.getUserCode());
            }
            File newFile = new File("fx.jpg");
            File newFileT = new File("simsunb.ttf");
            try {
                InputStream stream =  getClass().getClassLoader().getResourceAsStream("fx.jpg");
                FileUtils.copyInputStreamToFile(stream, newFile);
                // if(!newFile.exists()){
                //     InputStream stream =  getClass().getClassLoader().getResourceAsStream("fx.jpg");
                //     FileUtils.copyInputStreamToFile(stream, newFile);
                // }
                if(!newFileT.exists()){
                    InputStream streamT =  getClass().getClassLoader()
                            .getResourceAsStream("simsunb.ttf");
                    FileUtils.copyInputStreamToFile(streamT, newFileT);
                }
            } catch (IOException e) {

                throw new CustomException(e.getMessage());
            }

            try {
                String url=fsConfig.getTuiImgPath()+"/tui-"+getUserId()+".jpg";
                File outputFile = new File(url);
                if(!outputFile.exists())
                {
                    try {
                        outputFile.createNewFile();

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Font font =  Font.createFont(Font.TRUETYPE_FONT, newFileT);
                Font f= font.deriveFont(Font.PLAIN,50);
                ImgUtil.pressText(//
                        newFile,
                        outputFile,
                        user.getNickname()+"邀您加入",
                        Color.BLACK,
                        f, //字体
                        -60, //x坐标修正值。 默认在中间，偏移量相对于中间偏移
                        900, //y坐标修正值。 默认在中间，偏移量相对于中间偏移
                        0.8f//透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
                );
                ImgUtil.pressText(//
                        outputFile,
                        outputFile,
                         "邀请码:"+user.getUserCode(),
                        Color.BLACK,
                        f, //字体
                        -40, //x坐标修正值。 默认在中间，偏移量相对于中间偏移
                        1000, //y坐标修正值。 默认在中间，偏移量相对于中间偏移
                        0.8f//透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
                );
                File qr = new File(fsConfig.getTuiImgPath()+"/qr-"+getUserId()+".png");
                if(!qr.exists())
                {
                    try {
                        qr.createNewFile();

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                QrCodeUtil.generate(fsConfig.getUrl()+"/distribution?userCode="+user.getUserCode(), 300, 300,
                        FileUtil.file(fsConfig.getTuiImgPath()+"/qr-"+getUserId()+".png"));
                ImgUtil.pressImage(
                        outputFile,
                        outputFile,
                        ImgUtil.read(qr), //QR图片
                        -400, //x坐标修正值。 默认在中间，偏移量相对于中间偏移
                        900, //y坐标修正值。 默认在中间，偏移量相对于中间偏移
                        1f
                );
                return R.ok().put("url","profile/tui/tui-"+getUserId()+".jpg");
            } catch (Exception e) {
                e.printStackTrace();
                return R.error("操作异常");
            }
        } catch (Exception e){

            return R.error("操作异常");
        }
    }

    @Login
    @ApiOperation("获取推荐海报")
    @GetMapping("/getTuiImg")
    public R getTuiImg(HttpServletRequest request){
        log.info("获取推荐海报 headers: {}", ServletUtil.getHeaderMap(request));

        try {
            String userId = getUserId();
            log.info("获取用户ID: {}", userId);
            if (StringUtils.isEmpty(userId)) {
                log.error("用户ID为空");
                return R.error("用户ID不能为空");
            }
            // 检查是否已存在海报，避免重复生成
            String resultUrl = "profile/tui/tui-" + userId + ".jpg";
            File existingPoster = new File(fsConfig.getTuiImgPath() + "/tui-" + userId + ".jpg");
            if (existingPoster.exists() && existingPoster.lastModified() > System.currentTimeMillis() - 24 * 60 * 60 * 1000) {
                log.info("使用已存在的海报: {}", resultUrl);
                return R.ok().put("url", resultUrl);
            }
            FsUserScrm user = userService.selectFsUserById(Long.parseLong(userId));
            if (user == null) {
                log.error("未找到用户信息，用户ID: {}", userId);
                return R.error("用户信息不存在");
            }
            log.info("查询到用户信息: 用户ID={}, 昵称={}", userId, user.getNickName());

            // 确保用户有邀请码
            if(StringUtils.isEmpty(user.getUserCode())){
                log.info("用户邀请码为空，开始生成新的邀请码");
                FsUserScrm userMap = new FsUserScrm();
                userMap.setUserId(user.getUserId());
                userMap.setUserCode(OrderUtils.genUserCode());
                userService.updateFsUser(userMap);
                user.setUserCode(userMap.getUserCode());
                log.info("成功生成并更新用户邀请码: {}", userMap.getUserCode());
            }
            return generatePosterOptimized(user, userId);
        } catch (NumberFormatException e) {
            log.error("用户ID格式错误: {}", e.getMessage(), e);
            return R.error("用户ID格式错误");
        } catch (Exception e){
            log.error("获取推荐海报失败: {}", e.getMessage(), e);
            return R.error("操作异常: " + e.getMessage());
        }
    }

    /**
     * 优化的海报生成方法 - 在内存中完成所有图片操作
     */
    private R generatePosterOptimized(FsUserScrm user, String userId) {
        log.info("开始生成用户海报，用户ID: {}", userId);

        try {
            // 确保输出目录存在
            String outputDir = fsConfig.getTuiImgPath();
            File outputDirFile = new File(outputDir);
            if (!outputDirFile.exists()) {
                outputDirFile.mkdirs();
            }
            // 并行加载资源
            CompletableFuture<BufferedImage> templateFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    log.info("开始加载海报模板图片");
                    try (InputStream templateStream = fileCacheService.getTemplateStream()) {
                        BufferedImage image = ImageIO.read(templateStream);
                        log.info("海报模板图片加载成功");
                        return image;
                    }
                } catch (Exception e) {
                    log.error("加载模板图片失败: {}", e.getMessage(), e);
                    throw new RuntimeException("加载模板图片失败", e);
                }
            });
            CompletableFuture<Font> fontFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    log.info("开始加载字体文件");
                    try (InputStream fontStream = fileCacheService.getFontStream()) {
                        Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
                        font = font.deriveFont(Font.PLAIN, 50f);
                        log.info("字体文件加载成功");
                        return font;
                    }
                } catch (Exception e) {
                    log.error("字体加载失败，使用默认字体: {}", e.getMessage());
                    return new Font(Font.SANS_SERIF, Font.PLAIN, 50);
                }
            });
            CompletableFuture<BufferedImage> qrFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    // 改为小程序码生成
                    WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(0).getAppid());
                    byte[] qrCodeBytes = wxService.getQrcodeService().createWxaCodeUnlimitBytes(
                            user.getUserCode(),           // scene - 分销用户码
                            "pages_shopping/promotion/distribution",   // page - 目标页面（需要你确认）
                            false,                        // checkPath - 检查页面是否存在
                            "release",                   // envVersion - 版本（release/trial/develop）
                            300,                         // width - 宽度
                            true,                        // autoColor - 自动配置线条颜色
                            null,                        // lineColor - 线条颜色（null使用默认）
                            false                        // isHyaline - 是否需要透明底色
                    );

                    return ImageIO.read(new ByteArrayInputStream(qrCodeBytes));

                } catch (Exception e) {
                    log.error("生成二维码失败: {}", e.getMessage(), e);
                    throw new RuntimeException("生成二维码失败", e);
                }
            });
            // 等待所有资源加载完成
            BufferedImage templateImage = templateFuture.get(10, TimeUnit.SECONDS);
            Font font = fontFuture.get(10, TimeUnit.SECONDS);
            BufferedImage qrImage = qrFuture.get(10, TimeUnit.SECONDS);
            if (templateImage == null) {
                log.error("模板图片加载失败");
                return R.error("模板图片加载失败");
            }
            // 在内存中完成所有图片合成操作
            BufferedImage finalImage = createFinalPoster(templateImage, font, qrImage, user);
            // 只进行一次文件写入
            String outputPath = outputDir + "/tui-" + userId + ".jpg";
            File outputFile = new File(outputPath);

            // 使用高质量的JPEG编码
            writeHighQualityJPEG(finalImage, outputFile);

            String resultUrl = "profile/tui/tui-" + userId + ".jpg";
            log.info("海报生成完成，返回URL: {}", resultUrl);
            return R.ok().put("url", resultUrl);
        } catch (Exception e) {
            log.error("生成海报过程出现异常: {}", e.getMessage(), e);
            return R.error("生成海报失败: " + e.getMessage());
        }
    }

    /**
     * 在内存中完成所有图片合成操作
     */
    private BufferedImage createFinalPoster(BufferedImage templateImage, Font font,
                                            BufferedImage qrImage, FsUserScrm user) {
        log.info("开始在内存中合成最终海报");

        // 创建最终图片
        BufferedImage finalImage = new BufferedImage(
                templateImage.getWidth(),
                templateImage.getHeight(),
                BufferedImage.TYPE_INT_RGB
        );

        Graphics2D g2d = finalImage.createGraphics();
        try {
            // 设置高质量渲染
            setupHighQualityRendering(g2d);

            // 绘制模板图片
            g2d.drawImage(templateImage, 0, 0, null);

            // 绘制文本
            drawUserText(g2d, font, user, templateImage.getWidth());

            // 绘制二维码
            drawQRCode(g2d, qrImage, templateImage);

            log.info("海报合成完成");
            return finalImage;

        } finally {
            g2d.dispose();
        }
    }

    /**
     * 设置高质量渲染参数
     */
    private void setupHighQualityRendering(Graphics2D g2d) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    }

    /**
     * 绘制用户文本信息
     */
    private void drawUserText(Graphics2D g2d, Font font, FsUserScrm user, int imageWidth) {
        g2d.setFont(font);
        g2d.setColor(Color.BLACK);

        String nickname = StringUtils.isEmpty(user.getNickName()) ? "用户" : user.getNickName();
        FontMetrics fm = g2d.getFontMetrics();

        // 绘制邀请文本
        String nicknameText = nickname + "邀您加入";
        int textWidth = fm.stringWidth(nicknameText);
        int x = (imageWidth - textWidth) / 2;
        int y = 900;
        g2d.drawString(nicknameText, x, y);

        // 绘制邀请码
        String inviteText = "邀请码:" + user.getUserCode();
        int inviteTextWidth = fm.stringWidth(inviteText);
        int inviteX = (imageWidth - inviteTextWidth) / 2;
        int inviteY = 1000;
        g2d.drawString(inviteText, inviteX, inviteY);

        log.info("用户文本绘制完成");
    }

    /**
     * 绘制二维码
     */
    private void drawQRCode(Graphics2D g2d, BufferedImage qrImage, BufferedImage templateImage) {
        int qrX =  100;
        int qrY = templateImage.getHeight()-qrImage.getHeight()-100;
        g2d.drawImage(qrImage, qrX, qrY, null);
        log.info("二维码绘制完成");
    }
    /**
     * 高质量JPEG图片写入
     */
    private void writeHighQualityJPEG(BufferedImage image, File outputFile) throws IOException {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
        if (!writers.hasNext()) {
            throw new IllegalStateException("No JPEG writers found");
        }

        ImageWriter writer = writers.next();
        ImageWriteParam param = writer.getDefaultWriteParam();

        if (param.canWriteCompressed()) {
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(0.9f); // 高质量压缩
        }

        try (FileImageOutputStream output = new FileImageOutputStream(outputFile)) {
            writer.setOutput(output);
            writer.write(null, new IIOImage(image, null, null), param);
        } finally {
            writer.dispose();
        }

        log.info("高质量JPEG图片写入完成: {}", outputFile.getAbsolutePath());
    }

    @Login
    @ApiOperation("获取我的推荐人")
    @GetMapping("/getMyTuiList")
    public R getMyTuiList(BaseQueryParam param, HttpServletRequest request){
        PageHelper.startPage(param.getPage(), param.getPageSize());
        List<FsUserTuiVO> list= userService.selectFsUserTuiList(getUserId());
        PageInfo<FsUserTuiVO> listPageInfo=new PageInfo<>(list);
        return R.ok().put("data",listPageInfo);
    }

//    @Login
    @ApiOperation("获取用户金额")
    @GetMapping("/getTuiMoney")
    public R getMemberTuiMoney(HttpServletRequest request){
        try {
            String userId=getUserId();
            FsUserScrm user=userService.selectFsUserById(Long.parseLong(userId));
            BigDecimal yesterdayMoney=userBillService.selectFsUserBillTotalByUserId(userId,"brokerage_price");
            return R.ok().put("nowMoney",user.getNowMoney()).put("brokeragePrice",user.getBrokeragePrice()).put("yesterdayMoney",yesterdayMoney);
        } catch (Exception e){
            log.error("获取用户金额异常",e);
            return R.error("操作异常");
        }
    }

    @Login
    @ApiOperation("获取我的推荐订单")
    @GetMapping("/getMyTuiOrderList")
    public R getMyTuiOrderList(BaseQueryParam param,  HttpServletRequest request){
        PageHelper.startPage(param.getPage(), param.getPageSize());
        List<FsStoreOrderTuiVO> list= orderService.selectFsStoreOrderTuiListVO(getUserId());
        PageInfo<FsStoreOrderTuiVO> listPageInfo=new PageInfo<>(list);
        return R.ok().put("data",listPageInfo);
    }

    @Login
    @ApiOperation("获取用户佣金记录")
    @GetMapping("/getTuiMoneyLogs")
    public R getTuiMoneyLogs(BaseQueryParam param, HttpServletRequest request){
        PageHelper.startPage(param.getPage(), param.getPageSize());
        FsUserBillScrm map=new FsUserBillScrm();
        map.setUserId(Long.parseLong(getUserId()));
        map.setCategory("brokerage_price");
        List<FsUserBillScrm> list=userBillService.selectFsUserBillList(map);
        PageInfo<FsUserBillScrm> listPageInfo=new PageInfo<>(list);
        return R.ok().put("data",listPageInfo);
    }


    @Login
    @ApiOperation("获取商品足迹")
    @GetMapping("/getProductFoots")
    public R getProductFoots(FsStoreProductRelationQueryParam param, HttpServletRequest request){
        PageHelper.startPage(param.getPage(), param.getPageSize());
        param.setUserId(Long.parseLong(getUserId()));
        List<FsStoreProductRelationQueryVO> list=productRelationService.selectFsStoreProductRelationListVOQuery(param);
        PageInfo<FsStoreProductRelationQueryVO> listPageInfo=new PageInfo<>(list);
        return R.ok().put("data",listPageInfo);
    }

    @Login
    @ApiOperation("删除足迹")
    @PostMapping("/delProductFoots")
    public R delProductFoots(@RequestBody FsStoreProductFootDelParam param, HttpServletRequest request){
        productRelationService.deleteFsStoreProductRelationById(param.getId());
        return R.ok("操作成功");
    }


    @Login
    @ApiOperation("申请提现")
    @PostMapping("/doExtract")
    public R doExtract(@Validated  @RequestBody FsUseDoExtractParam param, HttpServletRequest request){
        param.setUserId(Long.parseLong(getUserId()));
        return userExtractService.doExtract(param);
    }

    @Login
    @ApiOperation("获取提现记录")
    @GetMapping("/getExtractList")
    public R getExtractList(FsUseExtractQueryParam param, HttpServletRequest request){
        PageHelper.startPage(param.getPage(), param.getPageSize());
        param.setUserId(Long.parseLong(getUserId()));
        List<FsUserExtractVO> list=userExtractService.selectFsUserExtractListVOQuery(param);
        PageInfo<FsUserExtractVO> listPageInfo=new PageInfo<>(list);
        return R.ok().put("data",listPageInfo);
    }

    @Login
    @ApiOperation("修改用户信息")
    @PostMapping("/editUser")
    public R editUser(@RequestBody @Valid FsUserEditParam param, HttpServletRequest request){
        param.setUserId(Long.parseLong(getUserId()));
        log.info("【修改用户头像昵称】：{}",param);
        if (param.getNickname().length()>50){
            return R.error("请授权正确的昵称！");
        }
        if (StringUtils.isEmpty(param.getAvatar())){
            param.setAvatar("https://zkzh-2025.oss-cn-beijing.aliyuncs.com/fs/20250715/533c6f87cc2e4ba4a9504374bb58416d.png");
        }
        FsUserScrm user=new FsUserScrm();
        user.setUserId(Long.parseLong(getUserId()));
        user.setAvatar(param.getAvatar());
        user.setNickname(StringUtils.isNotBlank(param.getNickname())?param.getNickName():param.getNickname());
        if(userService.updateFsUser(user)>0){
            return R.ok("修改成功");
        }
        else{
            return R.error("修改失败");
        }
    }
    @Login
    @ApiOperation("申请推广员")
    @PostMapping("/applyPromoter")
    public R applyPromoter(@RequestBody FsUserPromoterApplyScrm param, HttpServletRequest request){
        param.setUserId(Long.parseLong(getUserId()));

        FsUserPromoterApplyScrm promoterApply=userPromoterApplyService.selectFsUserPromoterApplyByUserId(Long.parseLong(getUserId()));
        if(promoterApply!=null){
            return R.error("已提交申请,等待后台审核");
        }
        if(userPromoterApplyService.insertFsUserPromoterApply(param)>0){
            return R.ok("提交成功,等待后台审核");
        }
        else{
            return R.error("提交失败");
        }
    }

    @Login
    @ApiOperation("绑定推广员")
    @PostMapping("/bindPromoter")
    public R bindPromoter(@RequestBody FsUserBindPromoterParam param, HttpServletRequest request){

        FsUserScrm user=userService.selectFsUserById(Long.parseLong(getUserId()));
        if(user.getIsPromoter()==null||user.getIsPromoter()==0){
            FsUserScrm tuiUser=userService.selectFsUserByUserCode(param.getUserCode());
            if(tuiUser!=null){
                FsUserScrm userMap=new FsUserScrm();
                userMap.setUserId(user.getUserId());
                userMap.setIsPromoter(1);
                userMap.setSpreadUserId(tuiUser.getUserId());
                userService.updateFsUser(userMap);
                return R.ok("绑定成功");

            }
            else{
                return R.error("邀请码不存在");
            }
        }
        else{
            return R.error("您已是推广员,不能重复绑定");
        }
    }

    @ApiOperation("会员关联绑定销售")
    @PostMapping("/beMember")
    public ResponseResult<Boolean> becomeMember(@Valid @RequestBody FsUserCourseBeMemberParam param) {
        log.debug("会员关联绑定销售 param:{}", JSON.toJSONString(param));
        return fsUserService.becomeMember(param);
    }
}
