package com.ruoyi.api;

import com.ruoyi.ai.domain.*;
import com.ruoyi.ai.service.IAiManagerService;
import com.ruoyi.ai.service.IAiOrderService;
import com.ruoyi.ai.service.IAiTagService;
import com.ruoyi.ai.service.IByteService;
import com.ruoyi.api.request.ByteApiRequest;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginAiUser;
import com.ruoyi.common.utils.RandomStringUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TencentCosUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * AI-生成内容Controller
 */
@RestController
@RequestMapping("/api/ai")
@Api(tags = "生成内容")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ByteApiController extends BaseController {

    private final IByteService byteService;
    private final TencentCosUtil tencentCosUtil;
    private final IAiOrderService aiOrderService;
    private final IAiManagerService managerService;
    private final IAiTagService aiTagService;
    @Value("${byteapi.callBackUrl}")
    private String url;

    // 火山引擎配置
    @Value("${volcengine.ark.apiKey}")
    private String volcApiKey;
    @Value("${volcengine.ark.baseUrl}")
    private String volcBaseUrl;
    @Value("${volcengine.ark.callbackUrl}")
    private String volcCallbackUrl;

    @PostMapping("/promptToImg")
    @ApiOperation("文生图")
    public AjaxResult promptToImg(@RequestBody ByteApiRequest request) {
        String functionType = request.getFunctionType();
        if (null == functionType) {
            return AjaxResult.error("functionType is null");
        }

        String mode = request.getMode() != null ? request.getMode() : "image-to-video";
        AiManager aiManager = managerService.selectAiManagerByType(functionType);
        String tags = request.getTags();
        String text = request.getText();

        // 如果使用标签系统生成prompt
        if (StringUtils.isNotEmpty(tags)) {
            List<AiTag> aiTags = aiTagService.selectAiTagListByIds(request.getTags(), aiManager.getParentIdSort());
            List<String> tagPrompts = new ArrayList<>();
            for (AiTag aiTag : aiTags) {
                if (!aiTag.getAiId().equals(aiManager.getId())) {
                    return AjaxResult.error(-3, "Generation failed, please try again");
                }
                String p = "";
                if (StringUtils.isNotEmpty(aiTag.getPrompt())) {
                    String[] prompts = aiTag.getPrompt().split(Pattern.quote("^"));
                    int randomNumberWithin = RandomStringUtil.getRandomNumberWithin(prompts.length);
                    p = prompts[randomNumberWithin];
                }
                tagPrompts.add(p);
            }
            text = StringUtils.replacePlaceholders(aiManager.getPrompt(), tagPrompts);
        }

        if (StringUtils.isEmpty(text)) {
            return AjaxResult.error("text is null");
        }

        AiOrder aiOrder = aiOrderService.getAiOrder(functionType);
        try {
            if (aiOrder == null) {
                return AjaxResult.error(-1, "You have a low balance, please recharge");
            }
            aiOrder.setText(text);
            aiOrder.setMode(mode); // 记录生成模式

            ByteBodyReq byteBodyReq = new ByteBodyReq();
            // model由前端传入，默认为Seedance 2.0
            byteBodyReq.setModel(StringUtils.isNotEmpty(request.getModel()) ? 
                    request.getModel() : "ep-20260326165811-dlkth");
            byteBodyReq.setPrompt(text);
            byteBodyReq.setSequential_image_generation("disabled");
            byteBodyReq.setResponse_format("url");
            byteBodyReq.setSize("2K");
            byteBodyReq.setStream(false);
            byteBodyReq.setWatermark(false);
            ByteBodyRes byteBodyRes = byteService.promptToImg(byteBodyReq);
            List<ByteDataRes> data = byteBodyRes.getData();
            ByteDataRes byteDataRes = data.get(0);
            String url = byteDataRes.getUrl();
            url = tencentCosUtil.uploadFileByUrl(url);
            if (url == null) {
                // 判断生成失败，退回金额逻辑
                aiOrderService.orderFailure(aiOrder);
                return AjaxResult.error(-2, "generation failed, balance has been refunded");
            }
            aiOrder.setResult(url);
            aiOrderService.orderSuccess(aiOrder);
            return AjaxResult.success(url);
        } catch (Exception e) {
            // 判断生成失败，退回金额逻辑
            aiOrderService.orderFailure(aiOrder);
//            return AjaxResult.error(-2, "generation failed, balance has been refunded");
            throw new RuntimeException(e);
        }
    }

    @PostMapping("/imgToImg")
    @ApiOperation("图生图")
    @Transactional
    public AjaxResult imgToImg(@RequestBody ByteApiRequest request) throws Exception {
        String functionType = request.getFunctionType();
        if (null == functionType) {
            return AjaxResult.error("functionType is null");
        }

        AiManager aiManager = managerService.selectAiManagerByType(functionType);
        String tags = request.getTags();
        String text = "";
        if (StringUtils.isNotEmpty(tags)) {
            List<AiTag> aiTags = aiTagService.selectAiTagListByIds(request.getTags(), aiManager.getParentIdSort());
            List<String> tagPrompts = new ArrayList<>();
            for (AiTag aiTag : aiTags) {
                if (!aiTag.getAiId().equals(aiManager.getId())) {
                    return AjaxResult.error(-3, "Generation failed, please try again");
                }
                String p = "";
                if (StringUtils.isNotEmpty(aiTag.getPrompt())) {
                    String[] prompts = aiTag.getPrompt().split(Pattern.quote("^"));
                    int randomNumberWithin = RandomStringUtil.getRandomNumberWithin(prompts.length);
                    p = prompts[randomNumberWithin];
                }
                tagPrompts.add(p);
            }
            text = StringUtils.replacePlaceholders(aiManager.getPrompt(), tagPrompts);
        } else {
            text = aiManager.getPrompt();
        }

        if (StringUtils.isEmpty(text)) {
            return AjaxResult.error("text is null");
        }

        Object firstUrl = request.getFirstUrl();
        if (null == firstUrl) {
            return AjaxResult.error("firstUrl is null");
        }
        AiOrder aiOrder = aiOrderService.getAiOrder(functionType);
        try {
            if (aiOrder == null) {
                return AjaxResult.error(-1, "You have a low balance, please recharge");
            }

            aiOrder.setText(text);

            aiOrder.setImg1(firstUrl.toString());
            ByteBodyReq byteBodyReq = new ByteBodyReq();
            byteBodyReq.setModel("ep-20251104104536-2gpgz");
            byteBodyReq.setPrompt(text);
            byteBodyReq.setImage(firstUrl);
            byteBodyReq.setSequential_image_generation("disabled");
            byteBodyReq.setResponse_format("url");
            byteBodyReq.setSize("2K");
            byteBodyReq.setStream(false);
            byteBodyReq.setWatermark(false);
            ByteBodyRes byteBodyRes = byteService.promptToImg(byteBodyReq);
            List<ByteDataRes> data = byteBodyRes.getData();
            ByteDataRes byteDataRes = data.get(0);
            String url = byteDataRes.getUrl();
            url = tencentCosUtil.uploadFileByUrl(url);
            if (url == null) {
                // 判断生成失败，退回金额逻辑
                aiOrderService.orderFailure(aiOrder);
                return AjaxResult.error(-2, "generation failed, balance has been refunded");
            }
            aiOrder.setResult(url);
            aiOrderService.orderSuccess(aiOrder);
            return AjaxResult.success(url);
        } catch (Exception e) {
            aiOrderService.orderFailure(aiOrder);
            throw new RuntimeException(e);
        }
    }

    @PostMapping("/imgToVideo")
    @ApiOperation("图生视频 (Seedance 2.0)")
    public AjaxResult imgToVideo(@RequestBody ByteApiRequest request) throws Exception {
        String functionType = request.getFunctionType();
        if (null == functionType) {
            return AjaxResult.error("functionType is null");
        }

        AiManager aiManager = managerService.selectAiManagerByType(functionType);
        String tags = request.getTags();
        String text = "";
        if (StringUtils.isNotEmpty(tags)) {
            List<AiTag> aiTags = aiTagService.selectAiTagListByIds(request.getTags(), aiManager.getParentIdSort());
            List<String> tagPrompts = new ArrayList<>();
            for (AiTag aiTag : aiTags) {
                if (!aiTag.getAiId().equals(aiManager.getId())) {
                    return AjaxResult.error(-3, "Generation failed, please try again");
                }
                String p = "";
                if (StringUtils.isNotEmpty(aiTag.getPrompt())) {
                    String[] prompts = aiTag.getPrompt().split(Pattern.quote("^"));
                    int randomNumberWithin = RandomStringUtil.getRandomNumberWithin(prompts.length);
                    p = prompts[randomNumberWithin];
                }
                tagPrompts.add(p);
            }
            text = StringUtils.replacePlaceholders(aiManager.getPrompt(), tagPrompts);
        } else {
            text = aiManager.getPrompt();
        }

        if (StringUtils.isEmpty(text)) {
            return AjaxResult.error("text is null");
        }

        Object firstUrl = request.getFirstUrl();
        if (null == firstUrl) {
            return AjaxResult.error("firstUrl is null");
        }

        AiOrder aiOrder = aiOrderService.getAiOrder(functionType);
        if (aiOrder == null) {
            return AjaxResult.error(-1, "You have a low balance, please recharge");
        }
        try {
            aiOrder.setText(text);
            aiOrder.setImg1(firstUrl.toString());

            Integer duration = request.getDuration() != null ? request.getDuration() : 4;

            ByteBodyReq byteBodyReq = new ByteBodyReq();
            // model由前端传入，默认为Seedance2.0
            byteBodyReq.setModel(StringUtils.isNotEmpty(request.getModel()) ? 
                    request.getModel() : "ep-20260326165811-dlkth");
            byteBodyReq.setCallback_url(volcCallbackUrl);

            // 构建符合火山引擎格式的content
            List<ContentItem> contentList = new ArrayList<>();
            
            // 文本提示词
            ContentItem textItem = new ContentItem();
            textItem.setType("text");
            textItem.setText(text);
            contentList.add(textItem);

            // 首帧图片
            ContentItem firstFrameItem = new ContentItem();
            firstFrameItem.setType("image_url");
            firstFrameItem.setRole("first_frame");
            ImageUrl firstImageUrl = new ImageUrl();
            firstImageUrl.setUrl(firstUrl.toString());
            firstFrameItem.setImageUrl(firstImageUrl);
            contentList.add(firstFrameItem);

            // 如果有尾帧
            String lastUrl = request.getLastUrl();
            if (StringUtils.isNotBlank(lastUrl)) {
                ContentItem lastFrameItem = new ContentItem();
                lastFrameItem.setType("image_url");
                lastFrameItem.setRole("last_frame");
                ImageUrl lastImageUrl = new ImageUrl();
                lastImageUrl.setUrl(lastUrl);
                lastFrameItem.setImageUrl(lastImageUrl);
                contentList.add(lastFrameItem);
                aiOrder.setImg2(lastUrl);
            }

            byteBodyReq.setContent(contentList);
            byteBodyReq.setDuration(duration);
            byteBodyReq.setResolution("720p");
            byteBodyReq.setRatio("3:4");

            ByteBodyRes byteBodyRes = byteService.imgToVideo(byteBodyReq);
            String id = byteBodyRes.getId();
            if (id == null) {
                aiOrderService.orderFailure(aiOrder);
                return AjaxResult.error(-2, "generation failed, balance has been refunded");
            }
            aiOrder.setResult(id);
            aiOrderService.orderSuccess(aiOrder);
            return AjaxResult.success(byteBodyRes);
        } catch (Exception e) {
            aiOrderService.orderFailure(aiOrder);
            throw new RuntimeException(e);
        }
    }

    @GetMapping(value = "/{id}")
    @ApiOperation("视频下载")
    public AjaxResult getInfo(@PathVariable("id") String id) throws Exception {
        ByteBodyRes byteBodyRes = byteService.uploadVideo(id);
        if ("succeeded".equals(byteBodyRes.getStatus())) {
            content content = byteBodyRes.getContent();
            String videoUrl = content.getVideo_url();
            videoUrl = tencentCosUtil.uploadFileByUrl(videoUrl);
            content.setVideo_url(videoUrl);
            AiOrder aiOrderByResult = aiOrderService.getAiOrderByResult(id);
            AiOrder aiOrder = new AiOrder();
            aiOrder.setId(aiOrderByResult.getId());
            aiOrder.setResult(videoUrl);
//            aiOrder.setUpdateBy(SecurityUtils.getLoginAiUser().getUsername());
            aiOrderService.updateAiOrder(aiOrder);
        }
        return AjaxResult.success(byteBodyRes);
    }

    @GetMapping(value = "/volcCallback")
    @ApiOperation("火山引擎视频回调")
    @Anonymous
    public AjaxResult volcCallback(@RequestBody ByteBodyRes byteBodyRes) throws Exception {
        if ("succeeded".equals(byteBodyRes.getStatus())) {
            String id = byteBodyRes.getId();
            content contentObj = byteBodyRes.getContent();
            if (contentObj != null && StringUtils.isNotEmpty(contentObj.getVideo_url())) {
                String videoUrl = contentObj.getVideo_url();
                videoUrl = tencentCosUtil.uploadFileByUrl(videoUrl);
                contentObj.setVideo_url(videoUrl);

                AiOrder aiOrderByResult = aiOrderService.getAiOrderByResult(id);
                if (aiOrderByResult != null) {
                    AiOrder aiOrder = new AiOrder();
                    aiOrder.setId(aiOrderByResult.getId());
                    aiOrder.setResult(videoUrl);
                    aiOrderService.updateAiOrder(aiOrder);
                }
            }
        }
        return AjaxResult.success("callback success");
    }

    @PostMapping(value = "/{id}/cancel")
    @ApiOperation("取消视频生成任务")
    public AjaxResult cancelTask(@PathVariable("id") String id) throws Exception {
        return byteService.cancelVideoTask(id);
    }

}
