package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.creation.dto.ai3d.AI3DTaskQueryDTO;
import com.lesingle.creation.dto.ai3d.CreateAI3DTaskDTO;
import com.lesingle.creation.entity.AI3DTask;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.mapper.AI3DTaskMapper;
import com.lesingle.creation.service.AI3DTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.creation.vo.ai3d.AI3DTaskVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AI 3D 任务服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AI3DTaskServiceImpl extends ServiceImpl<AI3DTaskMapper, AI3DTask>
        implements AI3DTaskService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AI3DTaskVO create(CreateAI3DTaskDTO dto, Long tenantId, Long userId) {
        AI3DTask task = new AI3DTask();
        task.setTenantId(tenantId);
        task.setUserId(userId);
        task.setInputType(dto.getInputType());
        task.setInputContent(dto.getInputContent());
        task.setGenerateType(dto.getGenerateType());
        task.setStatus("pending");
        task.setRetryCount(0);

        this.save(task);
        log.info("创建 AI 3D 任务成功，ID={}, 输入类型={}", task.getId(), dto.getInputType());

        // TODO: 调用腾讯混元 AI 服务进行 3D 生成
        // 这里应该异步调用外部 AI 服务，并在完成后更新任务状态

        return convertToVO(task);
    }

    @Override
    public AI3DTaskVO getDetail(Long id, Long tenantId) {
        AI3DTask task = this.getById(id);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException("任务不存在");
        }

        return convertToVO(task);
    }

    @Override
    public Page<AI3DTaskVO> pageQuery(AI3DTaskQueryDTO queryDTO, Long tenantId, Long userId) {
        Page<AI3DTask> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        LambdaQueryWrapper<AI3DTask> wrapper = new LambdaQueryWrapper<AI3DTask>()
                .eq(AI3DTask::getTenantId, tenantId)
                .eq(AI3DTask::getDeleted, 0)
                .eq(queryDTO.getStatus() != null, AI3DTask::getStatus, queryDTO.getStatus())
                .eq(queryDTO.getInputType() != null, AI3DTask::getInputType, queryDTO.getInputType())
                .eq(userId != null, AI3DTask::getUserId, userId)
                .orderByDesc(AI3DTask::getCreateTime);

        Page<AI3DTask> resultPage = this.page(page, wrapper);

        List<AI3DTaskVO> voList = resultPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        Page<AI3DTaskVO> voPage = new Page<>(
                resultPage.getCurrent(),
                resultPage.getSize(),
                resultPage.getTotal()
        );
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id, Long tenantId) {
        AI3DTask task = this.getById(id);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException("任务不存在");
        }

        // 只有 pending/processing 状态的任务可以取消
        if (!"pending".equals(task.getStatus()) && !"processing".equals(task.getStatus())) {
            throw new BusinessException("当前状态无法取消任务");
        }

        task.setStatus("timeout");
        this.updateById(task);
        log.info("取消 AI 3D 任务成功，ID={}", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AI3DTaskVO retry(Long id, Long tenantId) {
        AI3DTask task = this.getById(id);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException("任务不存在");
        }

        // 只有 failed 状态的任务可以重试
        if (!"failed".equals(task.getStatus())) {
            throw new BusinessException("只有失败的任务可以重试");
        }

        // 限制最大重试次数
        if (task.getRetryCount() >= 3) {
            throw new BusinessException("已达到最大重试次数");
        }

        task.setStatus("pending");
        task.setRetryCount(task.getRetryCount() + 1);
        task.setErrorMessage(null);
        this.updateById(task);
        log.info("重试 AI 3D 任务成功，ID={}, 重试次数={}", id, task.getRetryCount());

        // TODO: 重新调用 AI 服务

        return convertToVO(task);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id, Long tenantId) {
        AI3DTask task = this.getById(id);
        if (task == null || !task.getTenantId().equals(tenantId)) {
            throw new BusinessException("任务不存在");
        }

        task.setDeleted(1);
        this.updateById(task);
        log.info("删除 AI 3D 任务成功，ID={}", id);
    }

    /**
     * 更新任务状态（供异步回调使用）
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskStatus(Long taskId, String status, String resultUrl,
                                 String previewUrl, String errorMessage) {
        AI3DTask task = this.getById(taskId);
        if (task != null) {
            task.setStatus(status);
            if ("completed".equals(status)) {
                task.setResultUrl(resultUrl);
                task.setPreviewUrl(previewUrl);
                task.setCompleteTime(LocalDateTime.now());
            } else if ("failed".equals(status)) {
                task.setErrorMessage(errorMessage);
            }
            this.updateById(task);
            log.info("更新 AI 3D 任务状态，ID={}, 状态={}", taskId, status);
        }
    }

    // ========== 转换方法 ==========

    private AI3DTaskVO convertToVO(AI3DTask task) {
        AI3DTaskVO vo = new AI3DTaskVO();
        vo.setId(task.getId());
        vo.setInputType(task.getInputType());
        vo.setInputContent(task.getInputContent());
        vo.setGenerateType(task.getGenerateType());
        vo.setStatus(task.getStatus());
        vo.setResultUrl(task.getResultUrl());
        vo.setPreviewUrl(task.getPreviewUrl());
        vo.setResultUrls(task.getResultUrls());
        vo.setPreviewUrls(task.getPreviewUrls());
        vo.setErrorMessage(task.getErrorMessage());
        vo.setExternalTaskId(task.getExternalTaskId());
        vo.setRetryCount(task.getRetryCount());
        vo.setCreateTime(task.getCreateTime());
        vo.setCompleteTime(task.getCompleteTime());
        return vo;
    }
}
