package com.yaoai.api.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.yaoai.api.dto.asset.GlobalAssetDTO;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.common.response.ApiResponse;
import com.yaoai.domain.entity.GlobalAsset;
import com.yaoai.domain.mapper.GlobalAssetMapper;
import com.yaoai.pipeline.service.ImageGenPipelineService;
import com.yaoai.security.context.TenantContext;
import com.yaoai.storage.service.TosService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Tag(name = "资产库")
@RestController
@RequestMapping("/assets")
@RequiredArgsConstructor
public class GlobalAssetsController {

    private final GlobalAssetMapper globalAssetMapper;
    private final TosService tosService;
    private final ImageGenPipelineService imageGenPipelineService;

    @Operation(summary = "获取资产列表")
    @GetMapping
    public ApiResponse<List<GlobalAssetDTO>> list(
            @RequestParam(required = false) String type,
            @RequestParam(required = false, defaultValue = "personal") String library) {
        Long tenantId = TenantContext.get();
        List<GlobalAssetDTO> result = globalAssetMapper
                .findByTenantAndType(tenantId, type, library)
                .stream().map(GlobalAssetDTO::from).toList();
        return ApiResponse.success(result);
    }

    @Operation(summary = "创建资产")
    @PostMapping
    public ApiResponse<GlobalAssetDTO> create(@RequestBody Map<String, Object> body) {
        Long tenantId = TenantContext.get();
        Long creatorUserId = StpUtil.getLoginIdAsLong();

        GlobalAsset asset = new GlobalAsset();
        asset.setTenantId(tenantId);
        asset.setCreatorUserId(creatorUserId);
        asset.setName((String) body.getOrDefault("name", "未命名"));
        asset.setAssetType((String) body.getOrDefault("assetType", "character"));
        asset.setLibraryType((String) body.getOrDefault("libraryType", "personal"));
        asset.setTags((String) body.get("tags"));
        asset.setImageUrl((String) body.get("imageUrl"));
        asset.setImageTosKey((String) body.get("imageTosKey"));
        asset.setDescription((String) body.get("description"));
        asset.setIsFavorite(0);
        Object srcProject = body.get("sourceProjectId");
        if (srcProject instanceof Number) {
            asset.setSourceProjectId(((Number) srcProject).longValue());
        } else if (srcProject instanceof String srcProjectText && !srcProjectText.isBlank()) {
            asset.setSourceProjectId(Long.valueOf(srcProjectText));
        }

        globalAssetMapper.insert(asset);
        return ApiResponse.success(GlobalAssetDTO.from(asset));
    }

    @Operation(summary = "切换收藏状态")
    @PutMapping("/{id}/favorite")
    public ApiResponse<GlobalAssetDTO> toggleFavorite(@PathVariable Long id) {
        Long tenantId = TenantContext.get();
        GlobalAsset asset = globalAssetMapper.selectById(id);
        if (asset == null || !tenantId.equals(asset.getTenantId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "资产不存在");
        }
        asset.setIsFavorite(Integer.valueOf(1).equals(asset.getIsFavorite()) ? 0 : 1);
        globalAssetMapper.updateById(asset);
        return ApiResponse.success(GlobalAssetDTO.from(asset));
    }

    @Operation(summary = "更新资产")
    @PutMapping("/{id}")
    public ApiResponse<GlobalAssetDTO> update(@PathVariable Long id,
                                               @RequestBody Map<String, Object> body) {
        Long tenantId = TenantContext.get();
        GlobalAsset asset = globalAssetMapper.selectById(id);
        if (asset == null || !tenantId.equals(asset.getTenantId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "资产不存在");
        }
        if (body.containsKey("name")) asset.setName((String) body.get("name"));
        if (body.containsKey("tags")) asset.setTags((String) body.get("tags"));
        if (body.containsKey("description")) asset.setDescription((String) body.get("description"));
        if (body.containsKey("libraryType")) asset.setLibraryType((String) body.get("libraryType"));
        globalAssetMapper.updateById(asset);
        return ApiResponse.success(GlobalAssetDTO.from(asset));
    }

    @Operation(summary = "AI 生成资产图片")
    @PostMapping("/{id}/generate-image")
    public ApiResponse<GlobalAssetDTO> generateImage(@PathVariable Long id) {
        Long tenantId = TenantContext.get();
        Long userId = StpUtil.getLoginIdAsLong();
        GlobalAsset asset = globalAssetMapper.selectById(id);
        if (asset == null || !tenantId.equals(asset.getTenantId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "资产不存在");
        }
        if (!"prop".equals(asset.getAssetType())) {
            throw new BizException(ErrorCode.INVALID_PARAM, "当前仅支持生成道具图片");
        }

        Long projectKeyId = asset.getSourceProjectId() != null ? asset.getSourceProjectId() : 0L;
        String key = imageGenPipelineService.generateAndStore(
                tenantId,
                userId,
                projectKeyId,
                "global-assets/" + asset.getAssetType(),
                buildPropImagePrompt(asset)
        );
        asset.setImageTosKey(key);
        asset.setImageUrl(tosService.publicUrl(key));
        globalAssetMapper.updateById(asset);
        return ApiResponse.success(GlobalAssetDTO.from(asset));
    }

    @Operation(summary = "上传资产图片")
    @PostMapping(value = "/{id}/upload-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ApiResponse<GlobalAssetDTO> uploadImage(@PathVariable Long id,
                                                   @RequestPart("file") MultipartFile file) throws IOException {
        Long tenantId = TenantContext.get();
        GlobalAsset asset = globalAssetMapper.selectById(id);
        if (asset == null || !tenantId.equals(asset.getTenantId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "资产不存在");
        }
        if (file == null || file.isEmpty()) {
            throw new BizException(ErrorCode.INVALID_PARAM, "图片文件不能为空");
        }

        String contentType = file.getContentType() != null ? file.getContentType() : "application/octet-stream";
        if (!contentType.startsWith("image/")) {
            throw new BizException(ErrorCode.INVALID_PARAM, "请上传图片文件");
        }

        Long projectKeyId = asset.getSourceProjectId() != null ? asset.getSourceProjectId() : 0L;
        String key = TosService.buildKey(
                tenantId,
                projectKeyId,
                "global-assets/" + asset.getAssetType(),
                file.getOriginalFilename()
        );
        tosService.upload(key, file.getInputStream(), file.getSize(), contentType);
        asset.setImageTosKey(key);
        asset.setImageUrl(tosService.publicUrl(key));
        globalAssetMapper.updateById(asset);
        return ApiResponse.success(GlobalAssetDTO.from(asset));
    }

    @Operation(summary = "删除资产")
    @DeleteMapping("/{id}")
    public ApiResponse<Void> delete(@PathVariable Long id) {
        Long tenantId = TenantContext.get();
        GlobalAsset asset = globalAssetMapper.selectById(id);
        if (asset == null || !tenantId.equals(asset.getTenantId())) {
            throw new BizException(ErrorCode.NOT_FOUND, "资产不存在");
        }
        globalAssetMapper.deleteById(id);
        return ApiResponse.success();
    }

    private String buildPropImagePrompt(GlobalAsset asset) {
        String category = asset.getTags() != null && !asset.getTags().isBlank() ? asset.getTags() : "道具";
        String description = asset.getDescription() != null && !asset.getDescription().isBlank()
                ? asset.getDescription()
                : "根据名称和分类设计清晰可识别的影视道具";
        return """
                Cinematic AI short-drama prop reference image, single object only.
                Create one clear hero reference image for a prop used in video generation.
                Neutral clean studio background, three-quarter view, accurate material, scale cues, sharp silhouette, realistic lighting.
                No people, no hands, no environment clutter, no text, no labels, no watermark, no logo, no duplicated objects.
                Prop name: %s
                Prop category: %s
                Prop description: %s
                """.formatted(asset.getName(), category, description);
    }
}
