package cn.iocoder.yudao.module.system.service.dify;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.controller.admin.dify.vo.DifyWorkFlowRecordPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dify.vo.DifyWorkFlowRecordRespVO;
import cn.iocoder.yudao.module.system.controller.admin.dify.vo.DifyWorkFlowRecordSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dify.vo.DifyWorkFlowRunReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dify.DifyWorkFlowRecordDO;
import cn.iocoder.yudao.module.system.dal.mysql.dify.DifyWorkFlowRecordMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exceptionCustomMsg;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.COMMON_ERROR;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.COMMON_NOT_FOUND;

@Service
@Validated
@Slf4j
public class DifyWorkFlowRecordServiceImpl implements DifyWorkFlowRecordService {

    private static final String API_URL = "https://api.dify.ai/v1/workflows/run";

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Resource
    private DifyWorkFlowRecordMapper difyWorkFlowRecordMapper;

    @Resource
    private RestTemplate restTemplate;

    @Autowired
    private TenantMapper tenantMapper;
    @Override
    public Long create(DifyWorkFlowRecordSaveReqVO createReqVO) {
        DifyWorkFlowRecordDO workFlowRecord = BeanUtils.toBean(createReqVO, DifyWorkFlowRecordDO.class);
        difyWorkFlowRecordMapper.insert(workFlowRecord);
        return workFlowRecord.getId();
    }

    @Override
    public void update(DifyWorkFlowRecordSaveReqVO updateReqVO) {
        validateExists(updateReqVO.getId());
        DifyWorkFlowRecordDO updateObj = BeanUtils.toBean(updateReqVO, DifyWorkFlowRecordDO.class);
        difyWorkFlowRecordMapper.updateById(updateObj);
    }

    @Override
    public void delete(Long id) {
        validateExists(id);
        difyWorkFlowRecordMapper.deleteById(id);
    }

    @Override
    public DifyWorkFlowRecordRespVO get(Long id) {
        DifyWorkFlowRecordDO workFlowRecord = difyWorkFlowRecordMapper.selectById(id);
        if (workFlowRecord == null) {
            return null;
        }
        return BeanUtils.toBean(workFlowRecord, DifyWorkFlowRecordRespVO.class);
    }

    @Override
    public PageResult<DifyWorkFlowRecordRespVO> getPage(DifyWorkFlowRecordPageReqVO pageReqVO) {
        PageResult<DifyWorkFlowRecordDO> pageResult = difyWorkFlowRecordMapper.selectPage(pageReqVO);
        return BeanUtils.toBean(pageResult, DifyWorkFlowRecordRespVO.class);
    }

    @Override
    public JSONObject workflowRun(DifyWorkFlowRunReqVO reqVO) {
        try {
            DifyWorkFlowRecordDO difyWorkFlowRecordDO = difyWorkFlowRecordMapper.selectOne(new LambdaQueryWrapperX<DifyWorkFlowRecordDO>()
                    .eq(DifyWorkFlowRecordDO::getNumber, reqVO.getWorkNumber()));
            if(difyWorkFlowRecordDO == null){
                throw exceptionCustomMsg(COMMON_ERROR, "调用 Dify 工作流失败，不存在该工作流编号" + reqVO.getWorkNumber());
            }
            ObjectNode root = OBJECT_MAPPER.createObjectNode();
            ObjectNode inputs = OBJECT_MAPPER.createObjectNode();
            inputs.put("tenantName", getTenantName(reqVO.getTenantId()));
            root.set("inputs", inputs);
            root.put("response_mode", "blocking");
            root.put("user", SecurityFrameworkUtils.getLoginUserNickname());
            String requestBody = OBJECT_MAPPER.writeValueAsString(root);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setAccept(java.util.Collections.singletonList(MediaType.APPLICATION_JSON));
            headers.set("Authorization", "Bearer " + difyWorkFlowRecordDO.getApiKey());

            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<String> response = restTemplate.postForEntity(API_URL, entity, String.class);
            String responseBody = response.getBody();
            log.info("workflowRun status={}, response={}", response.getStatusCodeValue(), responseBody);

            if (!response.getStatusCode().is2xxSuccessful() || responseBody == null) {
                throw exceptionCustomMsg(COMMON_ERROR, "调用 Dify 工作流失败");
            }

            JsonNode data = OBJECT_MAPPER.readTree(responseBody);
            return JSONObject.parseObject(data.path("data").path("outputs").path("text").asText());
        } catch (Exception e) {
            log.error("workflowRun 调用异常", e);
            throw exceptionCustomMsg(COMMON_ERROR, "调用 Dify 工作流异常: " + e.getMessage());
        }
    }

    private void validateExists(Long id) {
        if (id == null || difyWorkFlowRecordMapper.selectById(id) == null) {
            throw exception(COMMON_NOT_FOUND);
        }
    }

    private String getTenantName(Long tenantId){
        return tenantMapper.selectById(tenantId).getName();
    }
}
