package com.fs.app.controller;


import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.aiSoundReplication.VoiceCloneController;
import com.fs.aiSoundReplication.param.StatusResponse;
import com.fs.aiSoundReplication.param.TtsRequest;
import com.fs.aiSoundReplication.param.UploadResponse;
import com.fs.aiSoundReplication.service.impl.TtsServiceImpl;
import com.fs.aiSoundReplication.util.FileToMultipartConverterUtil;
import com.fs.app.annotation.Login;
import com.fs.app.param.FsBindCompanyUserParam;
import com.fs.common.annotation.Log;
import com.fs.common.config.FSConfig;
import com.fs.common.core.domain.AjaxResult;
import com.fs.common.core.domain.R;
import com.fs.common.core.page.TableDataInfo;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.enums.BusinessType;
import com.fs.common.exception.CustomException;
import com.fs.common.exception.ServiceException;
import com.fs.common.exception.file.OssException;
import com.fs.common.utils.SecurityUtils;
import com.fs.common.utils.poi.ExcelUtil;
import com.fs.common.utils.sign.Md5Utils;
import com.fs.company.domain.CompanyUser;
import com.fs.company.domain.CompanyUserCard;
import com.fs.company.domain.CompanyUserUser;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.company.param.CompanyUserLoginParam;
import com.fs.company.param.VcCompanyUser;
import com.fs.company.param.companyUserAddPrintParam;
import com.fs.company.service.ICompanyUserCardService;
import com.fs.company.service.ICompanyUserService;
import com.fs.company.service.ICompanyUserUserService;
import com.fs.config.ai.AiHostProper;
import com.fs.fastGpt.domain.FastgptChatVoiceHomo;
import com.fs.fastGpt.mapper.FastgptChatVoiceHomoMapper;
import com.fs.fastgptApi.util.AudioUtils;
import com.fs.fastgptApi.vo.AudioVO;
import com.fs.his.domain.FsPatient;
import com.fs.his.domain.FsUserInformationCollection;
import com.fs.his.param.*;
import com.fs.his.service.*;
import com.fs.his.utils.ConfigUtil;
import com.fs.his.vo.*;
import com.fs.hisStore.enums.SysConfigEnum;
import com.fs.sop.domain.QwSopTempVoice;
import com.fs.sop.service.IQwSopTempVoiceService;
import com.fs.system.oss.CloudStorageService;
import com.fs.system.oss.OSSFactory;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.lettuce.core.dynamic.annotation.Param;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Api("销售接口")
@RestController
@RequestMapping(value = "/app/companyUser")
public class CompanyUserController extends AppBaseController {


    @Autowired
    RedisCache redisCache;
    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private ICompanyUserUserService companyUserUserService;
    @Autowired
    private IFsPrescribeService fsPrescribeService;
    @Autowired
    private IQwSopTempVoiceService voiceService;
    @Autowired
    private FastgptChatVoiceHomoMapper fastgptChatVoiceHomoMapper;
    @Autowired
    AiHostProper aiHostProper;
    @Autowired
    private IFsUserInformationCollectionService fsUserInformationCollectionService;
    @Autowired
    private IFsQuestionAndAnswerService fsQuestionAndAnswerService;

    public static final String SOP_TEMP_VOICE_KEY = "sop:tempVoice";
    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private VoiceCloneController voiceCloneController;
    @Autowired
    private TtsServiceImpl ttsServiceImpl;

    @PostMapping("/login")
    public R Login(@RequestBody CompanyUserLoginParam param, HttpServletRequest request) {
        try {
            CompanyUser companyUser = companyUserService.selectUserByUserName(param.getUserName());
            if (companyUser == null || companyUser.getDelFlag().equals("1")) {
                return R.error("用户不存在");
            }
            if (!companyUser.getStatus().equals("0")) {
                return R.error("用户已禁用");

            }
            String pwd = SecurityUtils.encryptPassword(param.getPassword());
            if (!SecurityUtils.matchesPassword(param.getPassword(), companyUser.getPassword())) {
                return R.error("密码不正确");
            }
            redisCache.setCacheObject("company-user-token:" + Md5Utils.hash(companyUser.getUserId().toString()), companyUser.getUserId(), 100, TimeUnit.DAYS);
            return R.ok().put("companyUserToken", Md5Utils.hash(companyUser.getUserId().toString())).put("user", companyUser);
        } catch (Exception e) {

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

    @ApiOperation("获取销售信息")
    @GetMapping("/getUserInfo")
    public R getUserInfo(HttpServletRequest request) {

        Long userId = getCompanyUserId();
        if (userId == null) {
            return R.error(403, "用户失效");
        }
        CompanyUser companyUser = companyUserService.selectCompanyUserById(userId);
        if (companyUser == null || companyUser.getDelFlag().equals("1")) {
            return R.error("用户不存在");
        }
        if (!companyUser.getStatus().equals("0")) {
            return R.error("用户已禁用");
        }
        return R.ok().put("data", companyUser);
    }

    @Login
    @ApiOperation("绑定销售")
    @PostMapping("/bindCompanyUser")
    public R bindCompanyUser(@Validated @RequestBody FsBindCompanyUserParam param, HttpServletRequest request) {
        CompanyUserUser map = new CompanyUserUser();
        map.setCompanyUserId(param.getCompanyUserId());
        map.setUserId(Long.parseLong(getUserId()));
        List<CompanyUserUser> list = companyUserUserService.selectCompanyUserUserList(map);
        if (list == null || list.size() == 0) {
            CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
            if (companyUser != null && companyUser.getStatus().equals("0")) {
                map.setCompanyId(companyUser.getCompanyId());
                companyUserUserService.insertCompanyUserUser(map);
            }
        }
        return R.ok();
    }


    @Login
    @ApiOperation("上传声纹")
    @PostMapping("/addVoicePrintUrl")
    public R addVoicePrintUrl(@RequestBody companyUserAddPrintParam param) throws Exception {
        Long userId = getCompanyUserId();
        if (userId == null) {
            return R.error(403, "用户失效");
        }

        CompanyUser companyUser = new CompanyUser();
        companyUser.setUserId(userId);
        companyUser.setVoicePrintUrl(param.getVoicePrintUrl());

        //转换音频格式 mp3-wav
        String s = AudioUtils.audioWAVFromUrl(param.getVoicePrintUrl());//需要本地c盘根目录有ffmpeg.exe，silk_v3_decoder.exe，silk_v3_encoder.exe
        //保存文件并且上传存储桶
        System.out.println(s);
        File file = new File(s);
        FileInputStream fileInputStream = new FileInputStream(file);
        CloudStorageService storage = OSSFactory.build();
        String wavUrl = storage.uploadSuffix(fileInputStream, ".wav");
        //更新销售员工声纹
        companyUser.setVoicePrintUrl(wavUrl);
        companyUserMapper.updateCompanyUser(companyUser);
        /*判断sys的声纹复刻的配置value是不是2*/
        JSONObject vcConfig = configUtil.generateConfigByKey(SysConfigEnum.VS_CONFIG.getKey());
        if (vcConfig != null && !vcConfig.isEmpty() &&
//                !vcConfig.equals(new JSONObject()) &&
                "2".equals(vcConfig.getString("type"))) {
            /*走豆包直接不走原逻辑*/
            AjaxResult ajaxResult = uploadVoice(userId, wavUrl);
            if (!ajaxResult.get("code").equals(200)) {
                return R.error((String) ajaxResult.get("msg"));
            }
            voiceService.insertQwSopTempVoiceModel(userId);
            return R.ok();
        } else {
            try {
                CloseableHttpClient httpClient = HttpClients.createDefault();
                HttpPost httpPost = new HttpPost(aiHostProper.getCommonApi() + "/app/common/addCompanyAudio");
                String json = "{\"url\":\"" + wavUrl + "\",\"id\":\"" + userId + "\"}";
                StringEntity entity = new StringEntity(json);
                httpPost.setEntity(entity);
                httpPost.setHeader("Content-type", "application/json");
                HttpResponse response = httpClient.execute(httpPost);

                if (response.getStatusLine().getStatusCode() == 200) {
                    String responseBody = EntityUtils.toString(response.getEntity());
                    JSONObject jsonObject = JSON.parseObject(responseBody);
                    Integer code = (Integer) jsonObject.get("code");
                    if (code == 200) {
                        voiceService.insertQwSopTempVoiceModel(userId);
                        return R.ok();
                    }
                } else {
                    return R.error();
                }

                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return R.error();
        }
    }

    @ApiOperation("小程序销售绑定医生")
    @Log(title = "小程序销售绑定医生", businessType = BusinessType.UPDATE)
    @PostMapping("/bindDoctorId")
    public R binDoctor(@RequestBody CompanyUser companyUser) {
        return companyUserService.bindDoctor(companyUser);
    }

    @ApiOperation("小程序销售解除绑定医生")
    @Log(title = "小程序销售解除绑定医生", businessType = BusinessType.UPDATE)
    @GetMapping("/unBindDoctorId/{userId}")
    public R unBinDoctor(@PathVariable("userId") Long userId) {
        return companyUserService.unBindDoctor(userId);
    }

    @ApiOperation("获取公司收款码")
    @GetMapping("/getCompanyWxaCodeByPayment")
    public R getCompanyWxaCodeByPayment(@RequestParam("companyId") Long companyId, @RequestParam("appId") String appId, HttpServletRequest request) {
        //获取用户码
        String WxaCode = redisCache.getCacheObject("company-wxa-code:" + companyId + ":" + appId);
        return R.ok().put("data", WxaCode);
    }

    /**
     * 生成绑定连接或者绑定码
     *
     * @return
     */
    @Login
    @ApiOperation("获取绑定链接或者绑定码(唯一绑定)")
    @GetMapping("/getBindInfo")
    public R getBindInfo() {
        Long companyUserId = getCompanyUserId();
        if (companyUserId == null) {
            return R.error("该销售不存在");
        }
        return companyUserService.getBindInfo(companyUserId);

    }

    /**
     * 当只有模板文字text时，生成表中对应条的voice_url和user_voice_url
     *
     * @param id qw_sop_temp_voice的id
     * @return
     */
    @GetMapping("/companyUserVoice")
    public R companyUserVoice(@RequestParam("id") Long id) {
        AudioVO audioVO = new AudioVO();
        Long companyUserId = getCompanyUserId();
        List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + companyUserId);
        if (sopTempVoices != null && !sopTempVoices.isEmpty()) {
            List<Long> collect = sopTempVoices.stream().map(QwSopTempVoice::getId).collect(Collectors.toList());
            if (collect.contains(id)) {
                return R.ok().put("code", 202).put("msg", "该语音已进入转换,请完成后再试。");
            }
        }

        if (companyUserId != null) {
            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(companyUserId);
            if (companyUser != null && companyUser.getVoicePrintUrl() == null) {
                return R.ok().put("code", 201).put("msg", "账号未录制声纹，请录制后再试！");
            }
        }

        QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceById(id);
        if (qwSopTempVoice != null && qwSopTempVoice.getCompanyUserId() != null) {
            JSONObject vcConfig = configUtil.generateConfigByKey(SysConfigEnum.VS_CONFIG.getKey());
            if (vcConfig != null && !vcConfig.isEmpty() &&
//                    !vcConfig.equals(new JSONObject()) &&
                    "2".equals(vcConfig.getString("type"))) {
                VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(companyUserId);
                if (vcCompanyUser == null) throw new RuntimeException("用户不存在");
                audioVO = ttsServiceImpl.textToSpeech(new TtsRequest(null, null, vcCompanyUser.getSpeakerId(), qwSopTempVoice.getVoiceTxt().replace(" ", "")));
            } else {
                List<FastgptChatVoiceHomo> homos = fastgptChatVoiceHomoMapper.selectFastgptChatVoiceHomoList(new FastgptChatVoiceHomo());
                audioVO = AudioUtils.createUserUrlAndUrl(homos, qwSopTempVoice.getCompanyUserId(), qwSopTempVoice.getVoiceTxt().replace(" ", ""));
            }
            if (audioVO != null && audioVO.getWavUrl() != null && audioVO.getUrl() != null) {
                qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
                qwSopTempVoice.setUserVoiceUrl(audioVO.getWavUrl());
                qwSopTempVoice.setDuration(audioVO.getDuration());
                qwSopTempVoice.setRecordType(1);
                voiceService.updateQwSopTempVoice(qwSopTempVoice);
            }

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

    /**
     * 当只有user_voice_url时，生成表中对应条的voice_url
     *
     * @param userVoiceUrl wav格式的语音文件
     * @param id           qw_sop_temp_voice的id
     * @return
     */
    @GetMapping("/companyUserVoiceNew")
    public R companyUserVoiceNew(@RequestParam("id") Long id, @RequestParam("userVoiceUrl") String userVoiceUrl) {

        AudioVO audioVO = new AudioVO();
        Long companyUserId = getCompanyUserId();
        List<QwSopTempVoice> sopTempVoices = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY + ":" + companyUserId);
        if (sopTempVoices != null && !sopTempVoices.isEmpty()) {
            List<Long> collect = sopTempVoices.stream().map(QwSopTempVoice::getId).collect(Collectors.toList());
            if (collect.contains(id)) {
                return R.ok().put("code", 202).put("msg", "该语音已进入转换,请完成后再试。");
            }
        }

        QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceByIdAndUserVoiceUrl(id);
        if (qwSopTempVoice != null && qwSopTempVoice.getId() != null) {
            JSONObject vcConfig = configUtil.generateConfigByKey(SysConfigEnum.VS_CONFIG.getKey());
            if (vcConfig != null && !vcConfig.isEmpty() &&
//                    !vcConfig.equals(new JSONObject()) &&
                    "2".equals(vcConfig.getString("type"))) {
                VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(companyUserId);
                if (vcCompanyUser == null) throw new RuntimeException("用户不存在");
                audioVO = ttsServiceImpl.textToSpeech(new TtsRequest(null, null, vcCompanyUser.getSpeakerId(), qwSopTempVoice.getVoiceTxt().replace(" ", "")));
            } else {
                audioVO = AudioUtils.createVoiceUrl(qwSopTempVoice.getCompanyUserId(), userVoiceUrl);
            }

            if (audioVO != null && audioVO.getUrl() != null) {
                qwSopTempVoice.setVoiceUrl(audioVO.getUrl());
                qwSopTempVoice.setUserVoiceUrl(userVoiceUrl);
                qwSopTempVoice.setDuration(audioVO.getDuration());
                qwSopTempVoice.setRecordType(1);
                voiceService.updateQwSopTempVoice(qwSopTempVoice);
            }
        }
        return R.ok().put("data", audioVO);
    }


    @GetMapping("/query/{id}")
    public R querySopVoiceById(@PathVariable("id") Long id) {
        QwSopTempVoice tempVoice = voiceService.selectQwSopTempVoiceById(id);
        AudioVO audioVO = new AudioVO();
        if (tempVoice != null) {
            audioVO.setId(tempVoice.getId());
            audioVO.setVoiceTxt(tempVoice.getVoiceTxt());
            audioVO.setUrl(tempVoice.getVoiceUrl());
            audioVO.setWavUrl(tempVoice.getUserVoiceUrl());
            audioVO.setDuration(tempVoice.getDuration());
            audioVO.setRecordType(tempVoice.getRecordType());
        }
        return R.ok().put("data", audioVO);
    }

    @GetMapping("/querySopVoiceList")
    public TableDataInfo querySopVoiceList(@RequestParam("recordType") Integer recordType) {
        startPage();
        QwSopTempVoice sopTempVoice = new QwSopTempVoice();
        sopTempVoice.setRecordType(recordType);
        sopTempVoice.setCompanyUserId(getCompanyUserId());
        List<QwSopTempVoice> sopTempVoices = voiceService.selectQwSopTempVoiceNewList(sopTempVoice);
        return getDataTable(sopTempVoices);
    }

    /**
     * 一键转换
     *
     * @return
     */
    @GetMapping("/createUserAllVoice")
    public R createUserAllVoice() {
        QwSopTempVoice sopTempVoice = new QwSopTempVoice();
        sopTempVoice.setRecordType(0);
        Long companyUserId = getCompanyUserId();


        if (companyUserId != null) {
            CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(companyUserId);
            if (companyUser != null && companyUser.getVoicePrintUrl() == null) {
                return R.ok().put("code", 201).put("msg", "账号未录制声纹，请录制后再试！");
            }
        }

        sopTempVoice.setCompanyUserId(companyUserId);
        List<QwSopTempVoice> sopTempVoices = voiceService.selectQwSopTempVoiceNewList(sopTempVoice);
        if (sopTempVoices != null && !sopTempVoices.isEmpty()) {
            List<Long> newCompanyUserId = redisCache.getVoiceAllList(SOP_TEMP_VOICE_KEY);
            if (newCompanyUserId != null && newCompanyUserId.contains(companyUserId)) {
                return R.error().put("code", 202).put("msg", "语音还未转换完成，请完成后再添加!");
            } else {
                redisCache.setVoice(SOP_TEMP_VOICE_KEY, companyUserId);
                sopTempVoices.forEach(m -> m.setVoiceTxt(m.getVoiceTxt().replace(" ", "")));
                redisCache.setVoiceList(SOP_TEMP_VOICE_KEY + ":" + companyUserId, sopTempVoices);
                return R.ok().put("msg", "语音已加入队列进行转换，请耐心等待!");
            }
        }
        return null;
    }

    @Login
    @GetMapping("/getPrescribeList")
    public R getPrescribeList(FsPrescribeListDCompanyParam param) {
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        param.setCompanyUserId(getCompanyUserId());
        param.setStatus(1);
        List<FsPrescribeListDVO> list = fsPrescribeService.selectFsPrescribeListDVOByCompanyUser(param);
        PageInfo<FsPrescribeListDVO> listPageInfo = new PageInfo<>(list);
        return R.ok().put("data", listPageInfo);
    }

    /**
     * 查询用户信息采集列表问答列表
     */
    @GetMapping("/questionAndAnswer/allList")
    public TableDataInfo getQuestionAndAnswer() {
        List<OptionsVO> list = fsQuestionAndAnswerService.selectAllQuestionOptions();
        return getDataTable(list);
    }


    /**
     * 查询用户信息采集列表
     */
    @GetMapping("/informationCollection/list")
    @Login
    public TableDataInfo list(FsUserInformationCollection fsUserInformationCollection) {
        startPage();
        Long companyUserId = getCompanyUserId();
        fsUserInformationCollection.setCompanyUserId(companyUserId);
        List<FsUserInformationCollection> list = fsUserInformationCollectionService.selectFsUserInformationCollectionList(fsUserInformationCollection);
        return getDataTable(list);
    }


    /**
     * 获取用户信息采集详细信息
     */
    @Login
    @GetMapping(value = "/informationCollection/{id}")
    public R getInformationCollectionInfo(@PathVariable("id") Long id) {
        FsUserInformationCollection info = fsUserInformationCollectionService.selectFsUserInformationCollectionById(id);
        if (info == null) {
            return R.error("记录不存在");
        }
        // 仅允许查看归属当前销售的采集记录
        Long companyUserId = getCompanyUserId();
        if (info.getCompanyUserId() == null || !info.getCompanyUserId().equals(companyUserId)) {
            return R.error("无权查看该记录");
        }
        return R.ok().put("data", fsUserInformationCollectionService.selectFsUserInformationCollectionVoById(id));
    }

    /**
     * 新增用户信息采集
     */
    @Login
    @PostMapping("/informationCollection")
    public R add(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection) {
        Long companyUserId = getCompanyUserId();
        //查询用户是否绑定销售
        Long userId = fsUserInformationCollection.getUserId();
        if (userId == null || userId < 0) {
            return R.error("请选择绑定用户");
        }
        CompanyUserUser companyUserUser = new CompanyUserUser();
        companyUserUser.setCompanyUserId(companyUserId);
        companyUserUser.setUserId(userId);
        List<CompanyUserUser> companyUserUsers = companyUserUserService.selectCompanyUserUserList(companyUserUser);
        if (companyUserUsers == null || companyUserUsers.isEmpty()) {
            return R.error("用户未绑定该销售");
        }

        fsUserInformationCollection.setCompanyUserId(companyUserId);
        Long id = fsUserInformationCollectionService.insertFsUserInformationCollection(fsUserInformationCollection);
        return id == null ? R.error("新增失败") : R.ok().put("data", id);
    }

    /**
     * 修改用户信息采集
     */
    @PutMapping("/informationCollection")
    @Login
    public R edit(@RequestBody FsUserInformationCollectionParam fsUserInformationCollection) {
        Long companyUserId = getCompanyUserId();
        fsUserInformationCollection.setCompanyUserId(companyUserId);
        fsUserInformationCollectionService.update(fsUserInformationCollection);
        return R.ok();
    }

    /**
     * 删除用户信息采集
     */
    @Login
    @DeleteMapping("/informationCollection/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        Long companyUserId = getCompanyUserId();
        if (ids != null) {
            for (Long id : ids) {
                FsUserInformationCollection info = fsUserInformationCollectionService.selectFsUserInformationCollectionById(id);
                if (info == null || info.getCompanyUserId() == null || !info.getCompanyUserId().equals(companyUserId)) {
                    return AjaxResult.error("无权删除所选记录");
                }
            }
        }
        return toAjax(fsUserInformationCollectionService.deleteFsUserInformationCollectionByIds(ids));
    }

    @GetMapping("/informationCollection/getInfo")
    public AjaxResult getInformationCollection(FsUserInformationCollection fsUserInformationCollection) {
        return AjaxResult.success(fsUserInformationCollectionService.getInfo(fsUserInformationCollection));
    }

    /**
     * 上传音频豆包
     *
     * @param voicePrintUrl
     * @return
     * @throws Exception
     */
    @PostMapping("/uploadVoice")
    public AjaxResult uploadVoice(
            Long userId,
            String voicePrintUrl) throws Exception {
        if (userId == null) userId = 123L;
        VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(userId);
        if (vcCompanyUser == null) {
            return AjaxResult.error("用户没有声纹槽位，请联系管理员");
        }
        if (vcCompanyUser.getTimes() != null && vcCompanyUser.getTimes() >= 5)
            return AjaxResult.error("用户已上传声纹达到上限");
        vcCompanyUser.setUploadUrl(voicePrintUrl);
        File file = downloadFileFromUrl(voicePrintUrl);
        /*获取文件时长*/
        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
        AudioFormat format = audioInputStream.getFormat();
        long frames = audioInputStream.getFrameLength();
        // 计算时长（秒）= 总帧数 / 帧率
        Double duration = (double) frames / format.getFrameRate();
        audioInputStream.close();
        MultipartFile convert = FileToMultipartConverterUtil.convert(file);
        R r = voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), convert, 1, 0);
        if (r.get("code") != "200")
            return AjaxResult.error("上传声纹失败", r.get("msg"));
        vcCompanyUser.incrementTimes();
        vcCompanyUser.setUploadTime(duration);
        companyUserMapper.updateVcCompanyUser(vcCompanyUser);
        return AjaxResult.success(String.format("您已上传%d次声纹，总共有5次录入次数", vcCompanyUser.getTimes()));
    }
//    private static MultipartFile downloadAsMultipartFile(String fileUrl) throws Exception {
//        URL url = new URL(fileUrl);
//        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//
//        // 设置请求属性
//        connection.setRequestMethod("GET");
//        connection.setConnectTimeout(10000); // 10秒连接超时
//        connection.setReadTimeout(30000);    // 30秒读取超时
//        connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//        connection.setRequestProperty("Accept", "*/*");
//        connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
//
//        if (connection.getResponseCode() != 200) {
//            throw new IOException("下载失败，响应码: " + connection.getResponseCode());
//        }
//        // 获取内容类型和文件名
//        String contentType = connection.getContentType();
//        String fileName = getFileNameFromConnection(connection, fileUrl);
//        // 验证文件类型
//        if (!isValidAudioFileType(contentType, fileName)) {
//            throw new IOException("不支持的音频文件类型: " + contentType);
//        }
//        // 读取文件内容
//        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//        try (InputStream inputStream = connection.getInputStream()) {
//            byte[] buffer = new byte[8192];
//            int bytesRead;
//            while ((bytesRead = inputStream.read(buffer)) != -1) {
//                outputStream.write(buffer, 0, bytesRead);
//            }
//        }
//
//        byte[] fileBytes = outputStream.toByteArray();
//        // 验证文件大小
//        if (fileBytes.length == 0) {
//            throw new IOException("下载的文件为空");
//        }
//        // 关闭连接
//        connection.disconnect();
//
//        return new MockMultipartFile(
//                "audioFile",                   // form-data 字段名
//                fileName,                 // 原始文件名
//                contentType,
//                fileBytes                // 文件内容
//        );
//    }
//    private static boolean isValidAudioFileType(String contentType, String fileName) {
//        if (contentType != null) {
//            return contentType.startsWith("audio/");
//        }
//        if (fileName != null) {
//            String lowerFileName = fileName.toLowerCase();
//            return lowerFileName.endsWith(".mp3") || lowerFileName.endsWith(".wav") ||
//                    lowerFileName.endsWith(".pcm") || lowerFileName.endsWith(".m4a");
//        }
//        return false;
//    }
//    private static String getFileNameFromConnection(HttpURLConnection connection, String url) {
//        // 1. 尝试从 Content-Disposition 头获取
//        String contentDisposition = connection.getHeaderField("Content-Disposition");
//        if (contentDisposition != null && contentDisposition.contains("filename=")) {
//            String[] parts = contentDisposition.split("filename=");
//            if (parts.length > 1) {
//                String fileName = parts[1].replace("\"", "").trim();
//                if (!fileName.isEmpty()) {
//                    return fileName;
//                }
//            }
//        }
//
//        // 2. 从 URL 路径提取
//        try {
//            URL parsedUrl = new URL(url);
//            String path = parsedUrl.getPath();
//            if (path.contains("/")) {
//                String name = path.substring(path.lastIndexOf("/") + 1);
//                if (!name.isEmpty()) {
//                    return name;
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // 3. 默认文件名
//        return "downloaded_file";
//    }
//    /**
//     * 上传音频豆包
//     *
//     * @param voicePrintUrl
//     * @return
//     * @throws Exception
//     */
//    @PostMapping("/uploadVoiceTest")
//    public R uploadVoiceTest(
//            Long userId,
//            @RequestParam String voicePrintUrl) throws Exception {
//        if (userId == null) userId = 9565L;
//        VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(userId);
//        vcCompanyUser.setUploadUrl(voicePrintUrl);
//        File file = downloadFileFromUrl(voicePrintUrl);
//        /*获取文件时长*/
//        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
//        AudioFormat format = audioInputStream.getFormat();
//        long frames = audioInputStream.getFrameLength();
//        // 计算时长（秒）= 总帧数 / 帧率
//        Double duration = (double) frames / format.getFrameRate();
//        audioInputStream.close();
//        MultipartFile convert = FileToMultipartConverterUtil.convert(file);
//
//        voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), convert, 1, 0);
//        vcCompanyUser.incrementTimes();
//        vcCompanyUser.setUploadTime(duration);
//        companyUserMapper.updateVcCompanyUser(vcCompanyUser);
//        return R.ok();
//    }
//    /**
//     * 上传音频豆包
//     *
//     * @param
//     * @return
//     * @throws Exception
//     */
//    @PostMapping("/uploadVoiceTest1")
//    public R uploadVoiceTest1(
//            Long userId,@RequestParam MultipartFile audioFile
//            ) throws Exception {
//        if (userId == null) userId = 9565L;
//        VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(userId);
//        // 计算时长（秒）= 总帧数 / 帧率
//        UploadResponse uploadResponse = voiceCloneController.uploadVoice(vcCompanyUser.getSpeakerId(), audioFile, 1, 0);
//        return R.ok();
//    }

    /**
     * 获取文件扩展名
     *
     * @param fileUrl 文件路径
     * @return 文件扩展名
     */
    private static String getFileExtension(String fileUrl) {
        return fileUrl.substring(fileUrl.lastIndexOf("."));
    }

    private File downloadFileFromUrl(String fileUrl) throws IOException {
        InputStream inputStream = null;
        FileOutputStream outputStream = null;
        try {
            // 创建 HTTP 连接
            URL url = new URL(fileUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置Referer请求头
//            connection.setRequestProperty("Referer", "cos.his.cdwjyyh.com");
            connection.setRequestMethod("GET");
            connection.connect();

            // 检查是否成功连接
            if (connection.getResponseCode() != 200) {
                throw new ServiceException("无法下载音频文件，HTTP 响应码：" + connection.getResponseCode());
            }

            // 获取输入流
            inputStream = connection.getInputStream();

            // 创建临时文件，并指定存放地址
            String tempFileName = "temp_" + UUID.randomUUID() + "_" + getFileExtension(fileUrl);
            File destinationDirectory = new File("c:\\hook\\");

            // 参照 transferAudioSilk 方法，同步确保目录创建的线程安全
            synchronized (AudioUtils.class) {
                if (!destinationDirectory.exists()) {
                    destinationDirectory.mkdirs();
                }
            }

            // 将文件保存到指定路径
            File tempFile = new File(destinationDirectory, tempFileName);

            // 写入文件
            outputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            return tempFile;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) inputStream.close();
                if (outputStream != null) outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 文本转语音
     *
     * @param text
     * @param httpRequest
     * @return
     * @throws Exception
     */
    @PostMapping("/synthesizeSimple")
    public R synthesizeAndDownload(
            @ApiParam(value = "要合成的文本", required = true)
            @RequestParam String text,
            @RequestParam Long companyUserId,
            HttpServletRequest httpRequest) throws Exception {
        if (companyUserId == null) companyUserId = 123L;
//                getCompanyUserId();

        VcCompanyUser vcCompanyUser = companyUserMapper.selectVcCompanyUserByCompanyUserId(companyUserId);
        if (vcCompanyUser == null) throw new RuntimeException("用户不存在");
        AudioVO audioVO = voiceCloneController.synthesizeSimple(text, vcCompanyUser.getSpeakerId(), "mp3", 1);
        vcCompanyUser.setLatestTextToSpeechUrl(audioVO.getUrl());
        companyUserMapper.updateVcCompanyUser(vcCompanyUser);
        return R.ok().put("url", audioVO.getUrl());
    }

    @GetMapping("/status/{speakerId}")
    @ApiOperation("查询音色训练状态")
    public StatusResponse getTrainingStatus(
            @ApiParam(value = "音色ID", required = true)
            @PathVariable String speakerId) {
        return voiceCloneController.getTrainingStatus(speakerId);
    }

}
