package com.emotion.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emotion.common.PageResult;
import com.emotion.dto.request.coze.CozeApiCallPageRequest;
import com.emotion.dto.request.coze.CozeApiCallCreateRequest;
import com.emotion.dto.request.coze.CozeApiCallUpdateRequest;
import com.emotion.dto.response.coze.CozeApiCallResponse;
import com.emotion.entity.CozeApiCall;
import com.emotion.mapper.CozeApiCallMapper;
import com.emotion.service.CozeApiCallService;
import com.emotion.util.SnowflakeIdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Coze API调用记录服务实现类
 *
 * @author huazhongmin
 * @date 2025-07-23
 */
@Service
public class CozeApiCallServiceImpl extends ServiceImpl<CozeApiCallMapper, CozeApiCall> implements CozeApiCallService {

    @Autowired
    private SnowflakeIdGenerator snowflakeIdGenerator;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public PageResult<CozeApiCallResponse> getPage(CozeApiCallPageRequest request) {
        Page<CozeApiCall> page = new Page<>(request.getCurrent(), request.getSize());
        LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();

        // 根据请求参数构建查询条件
        if (StringUtils.hasText(request.getConversationId())) {
            wrapper.eq(CozeApiCall::getConversationId, request.getConversationId());
        }

        if (StringUtils.hasText(request.getUserId())) {
            wrapper.eq(CozeApiCall::getUserId, request.getUserId());
        }

        if (StringUtils.hasText(request.getBotId())) {
            wrapper.eq(CozeApiCall::getBotId, request.getBotId());
        }

        if (StringUtils.hasText(request.getStatus())) {
            wrapper.eq(CozeApiCall::getStatus, request.getStatus());
        }

        if (StringUtils.hasText(request.getRequestType())) {
            wrapper.eq(CozeApiCall::getRequestType, request.getRequestType());
        }

        if (StringUtils.hasText(request.getTraceId())) {
            wrapper.eq(CozeApiCall::getTraceId, request.getTraceId());
        }

        // 关键词搜索
        if (StringUtils.hasText(request.getKeyword())) {
            wrapper.and(w -> w.like(CozeApiCall::getRequestUrl, request.getKeyword())
                    .or().like(CozeApiCall::getAiReply, request.getKeyword())
                    .or().like(CozeApiCall::getUserMessage, request.getKeyword()));
        }

        wrapper.eq(CozeApiCall::getIsDeleted, 0);

        // 排序
        if (StringUtils.hasText(request.getOrderBy())) {
            if ("asc".equalsIgnoreCase(request.getOrderDirection())) {
                wrapper.orderByAsc(CozeApiCall::getStartTime);
            } else {
                wrapper.orderByDesc(CozeApiCall::getStartTime);
            }
        } else {
            wrapper.orderByDesc(CozeApiCall::getStartTime);
        }

        page = this.page(page, wrapper);
        return convertPageToPageResult(page);
    }

    @Override
    public CozeApiCallResponse getById(String id) {
        CozeApiCall apiCall = this.getBaseMapper().selectById(id);
        if (apiCall == null || apiCall.getIsDeleted() == 1) {
            return null;
        }
        return convertToResponse(apiCall);
    }

    @Override
    public CozeApiCallResponse create(CozeApiCallCreateRequest request) {
        CozeApiCall apiCall = new CozeApiCall();
        apiCall.setId(snowflakeIdGenerator.nextIdAsString()); // 使用雪花算法生成ID

        // 复制属性
        apiCall.setConversationId(request.getConversationId());
        apiCall.setMessageId(request.getMessageId());
        apiCall.setCozeChatId(request.getCozeChatId());
        apiCall.setCozeConversationId(request.getCozeConversationId());
        apiCall.setBotId(request.getBotId());
        apiCall.setWorkflowId(request.getWorkflowId());
        apiCall.setUserId(request.getUserId());
        apiCall.setRequestType(request.getRequestType());
        apiCall.setRequestUrl(request.getRequestUrl());
        apiCall.setRequestBody(request.getRequestBody());
        apiCall.setRequestHeaders(request.getRequestHeaders());
        apiCall.setUserMessage(request.getUserMessage());
        apiCall.setUserMessageType(request.getUserMessageType());
        apiCall.setAiReply(request.getAiReply());
        apiCall.setAiReplyType(request.getAiReplyType());
        apiCall.setResponseStatus(request.getResponseStatus());
        apiCall.setResponseBody(request.getResponseBody());
        apiCall.setResponseHeaders(request.getResponseHeaders());
        apiCall.setPollCount(request.getPollCount());
        apiCall.setFinalStatus(request.getFinalStatus());
        apiCall.setStatus(request.getStatus());
        apiCall.setDurationMs(request.getDurationMs());
        apiCall.setPromptTokens(request.getPromptTokens());
        apiCall.setCompletionTokens(request.getCompletionTokens());
        apiCall.setTotalTokens(request.getTotalTokens());
        apiCall.setCost(request.getCost());
        apiCall.setFunctionCalls(request.getFunctionCalls());
        apiCall.setFunctionResults(request.getFunctionResults());
        apiCall.setErrorCode(request.getErrorCode());
        apiCall.setErrorMessage(request.getErrorMessage());
        apiCall.setClientIp(request.getClientIp());
        apiCall.setUserAgent(request.getUserAgent());
        apiCall.setSessionId(request.getSessionId());
        apiCall.setTraceId(request.getTraceId());
        apiCall.setMetadata(request.getMetadata());

        this.save(apiCall);
        return convertToResponse(apiCall);
    }

    @Override
    public CozeApiCallResponse update(CozeApiCallUpdateRequest request) {
        CozeApiCall apiCall = this.getBaseMapper().selectById(request.getId());
        if (apiCall == null || apiCall.getIsDeleted() == 1) {
            return null;
        }

        // 只更新非空字段
        if (request.getConversationId() != null) {
            apiCall.setConversationId(request.getConversationId());
        }
        if (request.getMessageId() != null) {
            apiCall.setMessageId(request.getMessageId());
        }
        if (request.getCozeChatId() != null) {
            apiCall.setCozeChatId(request.getCozeChatId());
        }
        if (request.getCozeConversationId() != null) {
            apiCall.setCozeConversationId(request.getCozeConversationId());
        }
        if (request.getBotId() != null) {
            apiCall.setBotId(request.getBotId());
        }
        if (request.getWorkflowId() != null) {
            apiCall.setWorkflowId(request.getWorkflowId());
        }
        if (request.getUserId() != null) {
            apiCall.setUserId(request.getUserId());
        }
        if (request.getRequestType() != null) {
            apiCall.setRequestType(request.getRequestType());
        }
        if (request.getRequestUrl() != null) {
            apiCall.setRequestUrl(request.getRequestUrl());
        }
        if (request.getRequestBody() != null) {
            apiCall.setRequestBody(request.getRequestBody());
        }
        if (request.getRequestHeaders() != null) {
            apiCall.setRequestHeaders(request.getRequestHeaders());
        }
        if (request.getUserMessage() != null) {
            apiCall.setUserMessage(request.getUserMessage());
        }
        if (request.getUserMessageType() != null) {
            apiCall.setUserMessageType(request.getUserMessageType());
        }
        if (request.getAiReply() != null) {
            apiCall.setAiReply(request.getAiReply());
        }
        if (request.getAiReplyType() != null) {
            apiCall.setAiReplyType(request.getAiReplyType());
        }
        if (request.getResponseStatus() != null) {
            apiCall.setResponseStatus(request.getResponseStatus());
        }
        if (request.getResponseBody() != null) {
            apiCall.setResponseBody(request.getResponseBody());
        }
        if (request.getResponseHeaders() != null) {
            apiCall.setResponseHeaders(request.getResponseHeaders());
        }
        if (request.getPollCount() != null) {
            apiCall.setPollCount(request.getPollCount());
        }
        if (request.getFinalStatus() != null) {
            apiCall.setFinalStatus(request.getFinalStatus());
        }
        if (request.getStatus() != null) {
            apiCall.setStatus(request.getStatus());
        }
        if (request.getDurationMs() != null) {
            apiCall.setDurationMs(request.getDurationMs());
        }
        if (request.getPromptTokens() != null) {
            apiCall.setPromptTokens(request.getPromptTokens());
        }
        if (request.getCompletionTokens() != null) {
            apiCall.setCompletionTokens(request.getCompletionTokens());
        }
        if (request.getTotalTokens() != null) {
            apiCall.setTotalTokens(request.getTotalTokens());
        }
        if (request.getCost() != null) {
            apiCall.setCost(request.getCost());
        }
        if (request.getFunctionCalls() != null) {
            apiCall.setFunctionCalls(request.getFunctionCalls());
        }
        if (request.getFunctionResults() != null) {
            apiCall.setFunctionResults(request.getFunctionResults());
        }
        if (request.getErrorCode() != null) {
            apiCall.setErrorCode(request.getErrorCode());
        }
        if (request.getErrorMessage() != null) {
            apiCall.setErrorMessage(request.getErrorMessage());
        }
        if (request.getClientIp() != null) {
            apiCall.setClientIp(request.getClientIp());
        }
        if (request.getUserAgent() != null) {
            apiCall.setUserAgent(request.getUserAgent());
        }
        if (request.getSessionId() != null) {
            apiCall.setSessionId(request.getSessionId());
        }
        if (request.getTraceId() != null) {
            apiCall.setTraceId(request.getTraceId());
        }
        if (request.getMetadata() != null) {
            apiCall.setMetadata(request.getMetadata());
        }

        this.updateById(apiCall);
        return convertToResponse(apiCall);
    }

    @Override
    public boolean delete(String id) {
        CozeApiCall apiCall = this.getBaseMapper().selectById(id);
        if (apiCall == null) {
            return false;
        }

        // 使用 MyBatis-Plus 的 removeById 方法，自动处理逻辑删除
        return this.removeById(id);
    }

    @Override
    public Long countByUserId(String userId) {
        LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CozeApiCall::getUserId, userId)
               .eq(CozeApiCall::getIsDeleted, 0);
        return this.count(wrapper);
    }

    @Override
    public Long countByBotId(String botId) {
        LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CozeApiCall::getBotId, botId)
               .eq(CozeApiCall::getIsDeleted, 0);
        return this.count(wrapper);
    }

    @Override
    public Long countByStatus(String status) {
        LambdaQueryWrapper<CozeApiCall> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CozeApiCall::getStatus, status)
               .eq(CozeApiCall::getIsDeleted, 0);
        return this.count(wrapper);
    }

    @Override
    public Long sumTokensByUserId(String userId) {
        // 使用原生SQL或者查询后计算
        List<CozeApiCall> calls = this.list(new LambdaQueryWrapper<CozeApiCall>()
                .eq(CozeApiCall::getUserId, userId)
                .eq(CozeApiCall::getIsDeleted, 0)
                .isNotNull(CozeApiCall::getTotalTokens));
        return calls.stream().mapToLong(call -> call.getTotalTokens() != null ? call.getTotalTokens() : 0).sum();
    }

    @Override
    public BigDecimal sumCostByUserId(String userId) {
        List<CozeApiCall> calls = this.list(new LambdaQueryWrapper<CozeApiCall>()
                .eq(CozeApiCall::getUserId, userId)
                .eq(CozeApiCall::getIsDeleted, 0)
                .isNotNull(CozeApiCall::getCost));
        return calls.stream()
                .map(call -> call.getCost() != null ? call.getCost() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 转换为响应对象
     */
    private CozeApiCallResponse convertToResponse(CozeApiCall apiCall) {
        CozeApiCallResponse response = new CozeApiCallResponse();
        BeanUtils.copyProperties(apiCall, response);
        response.setId(apiCall.getId());
        if (apiCall.getCreateTime() != null) {
            response.setCreateTime(apiCall.getCreateTime().format(DATE_TIME_FORMATTER));
        }
        if (apiCall.getUpdateTime() != null) {
            response.setUpdateTime(apiCall.getUpdateTime().format(DATE_TIME_FORMATTER));
        }
        if (apiCall.getStartTime() != null) {
            response.setStartTime(apiCall.getStartTime().format(DATE_TIME_FORMATTER));
        }
        if (apiCall.getEndTime() != null) {
            response.setEndTime(apiCall.getEndTime().format(DATE_TIME_FORMATTER));
        }
        if (apiCall.getPollStartTime() != null) {
            response.setPollStartTime(apiCall.getPollStartTime().format(DATE_TIME_FORMATTER));
        }
        if (apiCall.getPollEndTime() != null) {
            response.setPollEndTime(apiCall.getPollEndTime().format(DATE_TIME_FORMATTER));
        }
        return response;
    }

    /**
     * 转换分页对象为PageResult对象
     */
    private PageResult<CozeApiCallResponse> convertPageToPageResult(Page<CozeApiCall> page) {
        PageResult<CozeApiCallResponse> pageResult = new PageResult<>();
        pageResult.setCurrent(page.getCurrent());
        pageResult.setSize(page.getSize());
        pageResult.setTotal(page.getTotal());
        pageResult.setPages(page.getPages());
        pageResult.setRecords(page.getRecords().stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList()));
        return pageResult;
    }
}