package com.yaoai.api.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yaoai.api.dto.asset.AssetDTO;
import com.yaoai.api.service.AssetService;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.domain.entity.Project;
import com.yaoai.domain.entity.ProjectAsset;
import com.yaoai.domain.mapper.ProjectAssetMapper;
import com.yaoai.domain.mapper.ProjectMapper;
import com.yaoai.security.context.TenantContext;
import com.yaoai.storage.service.TosService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AssetServiceImpl implements AssetService {

    private final ProjectAssetMapper assetMapper;
    private final ProjectMapper projectMapper;
    private final TosService tosService;


    @Override
    @Transactional
    public AssetDTO upload(Long projectId, MultipartFile file, String assetType) {
        Long tenantId = TenantContext.get();

        // verify project belongs to this tenant
        projectMapper.findActiveById(projectId, tenantId)
                .orElseThrow(() -> new BizException(ErrorCode.INVALID_PARAM, "项目不存在"));

        String type = assetType != null ? assetType : "other";
        String originalName = file.getOriginalFilename();
        String key = TosService.buildKey(tenantId, projectId, type, originalName);

        try {
            tosService.upload(key, file.getInputStream(), file.getSize(), file.getContentType());
        } catch (IOException e) {
            throw new BizException(ErrorCode.INTERNAL_ERROR, "文件读取失败");
        }

        ProjectAsset asset = new ProjectAsset();
        asset.setProjectId(projectId);
        asset.setTenantId(tenantId);
        asset.setName(originalName != null ? originalName : key);
        asset.setOriginalName(originalName != null ? originalName : "unknown");
        asset.setAssetType(type);
        asset.setMimeType(file.getContentType());
        asset.setFileSize(file.getSize());
        asset.setTosKey(key);
        assetMapper.insert(asset);

        // 上传封面图时同步更新项目 coverKey
        if ("cover".equals(type)) {
            try {
                projectMapper.update(null, Wrappers.<Project>lambdaUpdate()
                        .eq(Project::getId, projectId)
                        .set(Project::getCoverKey, key));
                log.debug("Updated coverKey for project {}: {}", projectId, key);
            } catch (Exception e) {
                log.warn("Failed to update coverKey for project {}: {}", projectId, e.getMessage());
            }
        }

        String url = tosService.publicUrl(key);
        return AssetDTO.from(asset, url);
    }

    @Override
    public List<AssetDTO> listByProject(Long projectId) {
        Long tenantId = TenantContext.get();
        projectMapper.findActiveById(projectId, tenantId)
                .orElseThrow(() -> new BizException(ErrorCode.INVALID_PARAM, "项目不存在"));

        return assetMapper.findByProject(projectId).stream()
                .map(a -> AssetDTO.from(a, tosService.publicUrl(a.getTosKey())))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void delete(Long projectId, Long assetId) {
        Long tenantId = TenantContext.get();
        ProjectAsset asset = assetMapper.findById(assetId, tenantId)
                .filter(a -> a.getProjectId().equals(projectId))
                .orElseThrow(() -> new BizException(ErrorCode.INVALID_PARAM, "素材不存在"));

        tosService.delete(asset.getTosKey());
        assetMapper.deleteById(assetId);
    }
}
