package tech.easyflow.admin.controller.ai;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.http.HttpUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tech.easyflow.admin.model.ai.ResourcePreviewVo;
import tech.easyflow.ai.entity.Resource;
import tech.easyflow.ai.service.ResourceService;
import tech.easyflow.ai.utils.DocUtil;
import tech.easyflow.common.domain.Result;
import tech.easyflow.common.entity.LoginAccount;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import tech.easyflow.common.web.controller.BaseCurdController;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.system.entity.vo.RoleCategoryAccessSnapshot;
import tech.easyflow.system.service.CategoryPermissionService;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;

import static tech.easyflow.ai.entity.table.ResourceTableDef.RESOURCE;

/**
 * 素材库
 *
 * @author ArkLight
 * @since 2025-06-27
 */
@RestController
@RequestMapping("/api/v1/resource")
public class ResourceController extends BaseCurdController<ResourceService, Resource> {
    private static final int RESOURCE_PREVIEW_CONTENT_LIMIT = 20_000;

    @javax.annotation.Resource
    private CategoryPermissionService categoryPermissionService;

    public ResourceController(ResourceService service) {
        super(service);
    }

    @Override
    protected Result<?> onSaveOrUpdateBefore(Resource entity, boolean isSave) {
        LoginAccount loginUser = SaTokenUtil.getLoginAccount();
        if (isSave) {
            String resourceUrl = entity.getResourceUrl();
            byte[] bytes = HttpUtil.downloadBytes(resourceUrl);
            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
            String suffix = FileTypeUtil.getType(stream, resourceUrl);
            entity.setSuffix(suffix);
            entity.setFileSize(BigInteger.valueOf(bytes.length));
            commonFiled(entity,loginUser.getId(),loginUser.getTenantId(), loginUser.getDeptId());
        } else {
            entity.setModified(new Date());
            entity.setModifiedBy(loginUser.getId());
        }
        return super.onSaveOrUpdateBefore(entity, isSave);
    }

    @Override
    protected Page<Resource> queryPage(Page<Resource> page, QueryWrapper queryWrapper) {
        applyCategoryPermission(queryWrapper);
        return super.queryPage(page, queryWrapper);
    }

    @Override
    public Result<List<Resource>> list(Resource entity, Boolean asTree, String sortKey, String sortType) {
        QueryWrapper queryWrapper = QueryWrapper.create(entity, buildOperators(entity));
        applyCategoryPermission(queryWrapper);
        queryWrapper.orderBy(buildOrderBy(sortKey, sortType, getDefaultOrderBy()));
        return Result.ok(service.list(queryWrapper));
    }

    @Override
    public Result<Resource> detail(String id) {
        Resource resource = service.getById(id);
        if (resource != null) {
            categoryPermissionService.assertCategoryResourceVisible("RESOURCE", resource.getCreatedBy(), resource.getCategoryId(), "无权限访问素材");
        }
        return Result.ok(resource);
    }

    /**
     * 获取素材预览内容。
     *
     * @param id 素材ID
     * @return 预览文本
     */
    @GetMapping("/previewContent")
    public Result<ResourcePreviewVo> previewContent(String id) {
        Resource resource = service.getById(id);
        if (resource == null) {
            throw new BusinessException("素材不存在");
        }
        categoryPermissionService.assertCategoryResourceVisible("RESOURCE", resource.getCreatedBy(), resource.getCategoryId(), "无权限访问素材");

        byte[] bytes = DocUtil.downloadFile(resource.getResourceUrl());
        String suffix = resolvePreviewSuffix(resource, bytes);
        String content = DocUtil.readPreviewContent(suffix, new ByteArrayInputStream(bytes));
        return Result.ok(buildPreviewVo(content));
    }

    private void applyCategoryPermission(QueryWrapper queryWrapper) {
        RoleCategoryAccessSnapshot access = categoryPermissionService.getCurrentAccess("RESOURCE");
        if (!access.isRestricted()) {
            return;
        }
        if (access.getCategoryIds().isEmpty()) {
            queryWrapper.eq(Resource::getCreatedBy, access.getAccountId());
            return;
        }
        queryWrapper.and(RESOURCE.CREATED_BY.eq(access.getAccountId()).or(RESOURCE.CATEGORY_ID.in(access.getCategoryIds())));
    }

    /**
     * 解析用于预览的文件后缀。
     *
     * @param resource 素材实体
     * @param bytes 文件字节
     * @return 标准化后的文件后缀
     */
    private String resolvePreviewSuffix(Resource resource, byte[] bytes) {
        if (StringUtils.hasText(resource.getSuffix())) {
            return DocUtil.normalizeSuffix(resource.getSuffix());
        }
        String detectedSuffix = FileTypeUtil.getType(new ByteArrayInputStream(bytes), resource.getResourceUrl());
        if (!StringUtils.hasText(detectedSuffix)) {
            throw new BusinessException("无法识别当前素材文件类型");
        }
        return DocUtil.normalizeSuffix(detectedSuffix);
    }

    /**
     * 构建预览返回对象，并在服务端截断超长内容。
     *
     * @param content 原始内容
     * @return 预览内容对象
     */
    private ResourcePreviewVo buildPreviewVo(String content) {
        String safeContent = content == null ? "" : content;
        boolean truncated = safeContent.length() > RESOURCE_PREVIEW_CONTENT_LIMIT;
        ResourcePreviewVo vo = new ResourcePreviewVo();
        vo.setContent(truncated ? safeContent.substring(0, RESOURCE_PREVIEW_CONTENT_LIMIT) : safeContent);
        vo.setTruncated(truncated);
        return vo;
    }
}
