package com.sonic.cow.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sonic.cow.client.ContextChatClient;
import com.sonic.cow.domain.bo.AiGen4Bo;
import com.sonic.cow.domain.bo.ExtJsonBo;
import com.sonic.cow.domain.entity.PromptConfig;
import com.sonic.cow.domain.input.GenAiUserContentV1Input;
import com.sonic.cow.domain.output.GenAiUserContentV1Output;
import com.sonic.cow.enums.PromptTypeEnum;
import com.sonic.cow.enums.SexEnums;
import com.sonic.cow.enums.ToastResultCode;
import com.sonic.cow.service.GenAiUserContentService;
import com.sonic.cow.service.PromptConfigService;
import com.sonic.cow.utils.DateUtils;
import com.sonic.cow.utils.LimitUtils;
import com.sonic.cow.utils.RedisKeyUtils;
import com.sonic.cow.utils.TextCleaner;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.StringWriter;
import java.util.Map;

/**
 * 一键生成AI人物基础信息
 */
@Slf4j
@Service
public class GenAiUserContentServiceImpl implements GenAiUserContentService {

    @Autowired
    private PromptConfigService promptConfigService;
    @Autowired
    private ContextChatClient contextChatClient;
    @Autowired
    private LimitUtils limitUtils;
    @Autowired
    private RedisKeyUtils redisKeyUtils;


    private static final Configuration configuration = new Configuration(Configuration.VERSION_2_3_29);

    @Override
    public GenAiUserContentV1Output genAiUserContentV1(Long userId, GenAiUserContentV1Input input) throws Exception {
        //处理入参中的性别的问题
        if (StringUtils.isNotEmpty(input.getSex())) {
            input.setSex(SexEnums.getSex(input.getSex()));
        }
        //处理生日为 age
        if (StringUtils.isNotEmpty(input.getBirthday())) {
            //将生日转换成年龄
            input.setAge(DateUtils.calculateAge(input.getBirthday()));
        }
        //处理介绍,默认为空字符串，不能要报错
        if (input.getIntroduction() == null) {
            input.setIntroduction("");
        }
        if(userId != -1) {
            //创建，编辑语音合成，1分钟内20次的限制
            boolean b = limitUtils.defaultLimitCheckByKey(redisKeyUtils.contentLimitKey(userId, input.getPtType()), 20, 60);
            ToastResultCode.REQUEST_LIMIT_ERROR.check(b);
        }

        //从数据库中获取系统提示词
        PromptConfig promptConfig = promptConfigService.getPromptTemplate(input.getPtType().name());
        if (promptConfig == null) {
            return null;
        }
        //获取对应的【人格特征】系统提示词（基于 性格|标签 的方式进行拼接的类型配置）
        PromptConfig personalityTraitsPromptConfig = promptConfigService.getPromptTemplate(input.getCharacterCode() + "|" + input.getTagCode());
        //系统提示词替换(根据参数名替换)
        Map<String, Object> data = JSONObject.parseObject(JSONObject.toJSONString(input), Map.class);
        //将人格的提示词内容，填充到入参对象中
        if (personalityTraitsPromptConfig != null) {
            data.put("personalityTraits", personalityTraitsPromptConfig.getPromptTemplate());
        }
        String formatted = processTemplate(promptConfig.getPromptTemplate(), data);
        AiGen4Bo bo = contextChatClient.aiGen4(formatted, promptConfig.getModel(), promptConfig.getTemperature(), promptConfig.getTopp());
        log.info("===> genAiUserContentV1 input : {}, temperature : {}, result : {}", formatted, promptConfig.getTemperature(), bo.getContent());
        //处理返回结果标签
        String result = TextCleaner.removeAiCharacterPrompt(bo.getContent());
        GenAiUserContentV1Output output = new GenAiUserContentV1Output();
        if(PromptTypeEnum.EXTRACT_JSON_CONTENT == input.getPtType()) {
            try {
                ExtJsonBo extJsonBo = JSONObject.parseObject(result, ExtJsonBo.class);
                output.setContent(JSONObject.toJSONString(extJsonBo));
            } catch (Exception e) {
                log.error("===> genAiUserContentV1 json parse error ", e);
                //解析失败的话，直接构造一个空对象给前端
                ExtJsonBo extJsonBo = new ExtJsonBo();
                output.setContent(JSONObject.toJSONString(extJsonBo));
            }
        } else {
            output.setContent(result);
        }
        output.setInput(bo.getInput());
        output.setOutput(bo.getOutput());
        output.setUrl(bo.getUrl());
        return output;
    }

    /**
     * 处理模板参数内容的替换
     *
     * @param templateString
     * @param data
     * @return
     * @throws Exception
     */
    public static String processTemplate(String templateString, Map<String, Object> data) throws Exception {
        Template template = new Template("template", templateString, configuration);
        StringWriter writer = new StringWriter();
        template.process(data, writer);
        return writer.toString();
    }


    @Override
    public <T> T genContent(String promptType, Object input, Class<T> clazz) throws Exception {
        //从数据库中获取系统提示词
        PromptConfig promptConfig = promptConfigService.getPromptTemplate(promptType);
        if (promptConfig == null) {
            return null;
        }
        //系统提示词替换(根据参数名替换)
        Map<String, Object> data = JSONObject.parseObject(JSONObject.toJSONString(input), Map.class);
        String formatted = processTemplate(promptConfig.getPromptTemplate(), data);
        //调用模型进行创作，并格式化输出
        String result = contextChatClient.aiGen3(formatted, promptConfig.getModel(), promptConfig.getTemperature(), promptConfig.getTopp());
        log.info("===> genContent result : {}", result);
        result = result.replaceAll("```json", "").replaceAll("```", "");
        return JSONObject.parseObject(result, clazz);
    }
}
