package com.agent.management.controller;

import com.agent.management.common.Result;
import com.agent.management.model.dto.*;
import com.agent.management.model.entity.Category;
import com.agent.management.model.entity.SkillCategory;
import com.agent.management.model.vo.*;
import com.agent.management.repository.CategoryRepository;
import com.agent.management.repository.SkillCategoryRepository;
import com.agent.management.service.CategoryService;
import com.agent.management.service.SkillService;
import com.agent.management.service.SkillVersionService;
import com.agent.management.service.TagService;
import com.agent.management.service.TranslationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/skills")
@RequiredArgsConstructor
public class SkillController {

    private final SkillService skillService;
    private final TranslationService translationService;
    private final TagService tagService;
    private final SkillVersionService skillVersionService;
    private final SkillCategoryRepository skillCategoryRepository;
    private final CategoryRepository categoryRepository;
    private final CategoryService categoryService;

    /**
     * 获取 Skill 列表（支持搜索、分类筛选、分页）
     */
    @GetMapping
    public Result<PageResult<SkillVO>> listSkills(
            @RequestParam(required = false) String search,
            @RequestParam(required = false) Long categoryId,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "12") int size) {

        List<SkillDTO> skills = skillService.listSkills();

        // 构建分类映射：folderName -> categoryId
        Map<String, Long> skillCategoryMap = skillCategoryRepository.findAll().stream()
                .collect(Collectors.toMap(SkillCategory::getSkillFolderName, SkillCategory::getCategoryId));
        // 分类名称映射
        Map<Long, String> categoryNameMap = categoryRepository.findAll().stream()
                .collect(Collectors.toMap(Category::getId, Category::getName));

        // 搜索过滤（同时匹配原文和翻译文本）
        String keyword = (search != null && !search.trim().isEmpty()) ? search.trim().toLowerCase() : null;
        if (keyword != null) {
            skills = skills.stream()
                    .filter(dto -> {
                        String name = dto.getName() != null ? dto.getName().toLowerCase() : "";
                        String desc = dto.getDescription() != null ? dto.getDescription().toLowerCase() : "";
                        // 仅翻译 displayName（name 为 kebab-case 标识，不翻译）
                        String displayName = dto.getDisplayName();
                        String translatedDisplayName = (displayName != null && !displayName.isEmpty())
                                ? translationService.getCachedTranslation(displayName) : null;
                        String translatedDesc = translationService.getCachedTranslation(dto.getDescription());
                        String tName = translatedDisplayName != null ? translatedDisplayName.toLowerCase() : "";
                        String tDesc = translatedDesc != null ? translatedDesc.toLowerCase() : "";
                        return name.contains(keyword) || desc.contains(keyword)
                                || tName.contains(keyword) || tDesc.contains(keyword);
                    })
                    .collect(Collectors.toList());
        }

        // 分类筛选（含子分类）
        if (categoryId != null) {
            List<Long> categoryIds = new ArrayList<>();
            categoryIds.add(categoryId);
            categoryIds.addAll(categoryService.getDescendantCategoryIds(categoryId));
            Set<Long> allowedIds = new HashSet<>(categoryIds);
            skills = skills.stream()
                    .filter(dto -> {
                        Long cid = skillCategoryMap.get(dto.getFolderName());
                        return cid != null && allowedIds.contains(cid);
                    })
                    .collect(Collectors.toList());
        }

        // 构建 VO
        List<SkillVO> voList = skills.stream()
                .map(dto -> {
                    SkillVO vo = toVOWithCache(dto);
                    Long cid = skillCategoryMap.get(dto.getFolderName());
                    if (cid != null) {
                        vo.setCategoryId(cid);
                        vo.setCategoryName(categoryNameMap.get(cid));
                    }
                    return vo;
                })
                .collect(Collectors.toList());

        // 异步翻译：仅翻译 displayName（name 为 kebab-case 标识符，不翻译）；
        // displayName 与 description 的触发条件相互独立，避免 displayName 为空时漏翻 description。
        for (SkillDTO dto : skills) {
            String displayName = dto.getDisplayName();
            String description = dto.getDescription();
            boolean needName = displayName != null && !displayName.isEmpty()
                    && translationService.getCachedTranslation(displayName) == null;
            boolean needDesc = description != null && !description.isEmpty()
                    && translationService.getCachedTranslation(description) == null;
            if (needName || needDesc) {
                translationService.asyncTranslateAndPush(
                        dto.getFolderName(),
                        displayName != null ? displayName : "",
                        description != null ? description : "");
            }
        }

        // 分页
        long total = voList.size();
        int fromIndex = (page - 1) * size;
        int toIndex = Math.min(fromIndex + size, voList.size());
        List<SkillVO> paged = fromIndex < voList.size()
                ? voList.subList(fromIndex, toIndex)
                : Collections.emptyList();

        return Result.success(PageResult.of(paged, total, page, size));
    }

    @PostMapping("/upload")
    public Result<Void> uploadSkill(@RequestParam("file") MultipartFile file) {
        skillService.createSkill(file);
        return Result.success("上传成功", null);
    }

    @PostMapping("/{folderName}/edit")
    public Result<Map<String, String>> editSkill(@PathVariable String folderName,
                                                  @RequestBody SkillUpdateDTO dto) {
        String effectiveFolder = skillService.updateSkill(folderName, dto);
        Map<String, String> result = new HashMap<>();
        result.put("folderName", effectiveFolder);
        result.put("renamed", String.valueOf(!effectiveFolder.equals(folderName)));
        return Result.success("更新成功", result);
    }

    @PostMapping("/{folderName}/delete")
    public Result<Void> deleteSkill(@PathVariable String folderName) {
        skillService.deleteSkill(folderName);
        return Result.success("删除成功", null);
    }

    /**
     * ⚠️ 临时运维接口：扫描全部 skill，将 folderName 与 SKILL.md name 不一致的统一重命名。
     * 用于历史数据一次性迁移，副作用同 saveSkillMd（含 _versions / 标签 / 分类 / 工作流引用）。
     * 建议迁移完成后移除此接口。
     */
    @PostMapping("/migrate-folders")
    public Result<Map<String, Object>> migrateFolders() {
        log.info("[Skill-Migrate] 触发历史数据迁移");
        return Result.success("迁移完成", skillService.migrateAllFoldersNormalize());
    }

    // ==================== 技能编辑相关 API ====================

    /**
     * 获取技能详情（含 SKILL.md 正文内容）
     */
    @GetMapping("/{folderName}/detail")
    public Result<SkillDetailVO> getSkillDetail(@PathVariable String folderName) {
        return Result.success(skillService.getSkillDetail(folderName));
    }

    /**
     * 保存 SKILL.md（智能合并元数据）。
     * 若 name 变化导致 folderName 变化，返回新的 folderName。
     */
    @PutMapping("/{folderName}/skill-md")
    public Result<Map<String, String>> saveSkillMd(@PathVariable String folderName,
                                                    @RequestBody Map<String, Object> body) {
        String name = (String) body.getOrDefault("name", "");
        String displayName = (String) body.get("displayName");
        String description = (String) body.getOrDefault("description", "");
        String bodyText = (String) body.getOrDefault("body", "");
        boolean canGenerateSkill = Boolean.TRUE.equals(body.get("canGenerateSkill"));

        // 解析 inputs / outputs
        List<IOField> inputs = parseIOFields(body.get("inputs"));
        List<IOField> outputs = parseIOFields(body.get("outputs"));

        String effectiveFolder = skillService.saveSkillMd(
                folderName, name, displayName, description,
                canGenerateSkill, inputs, outputs, bodyText);
        Map<String, String> result = new HashMap<>();
        result.put("folderName", effectiveFolder);
        result.put("renamed", String.valueOf(!effectiveFolder.equals(folderName)));
        return Result.success("保存成功", result);
    }

    @SuppressWarnings("unchecked")
    private List<IOField> parseIOFields(Object obj) {
        if (obj == null) return null;
        if (obj instanceof List) {
            return ((List<?>) obj).stream()
                    .map(item -> {
                        if (item instanceof java.util.Map) {
                            java.util.Map<String, Object> m = (java.util.Map<String, Object>) item;
                            IOField field = new IOField();
                            field.setName((String) m.getOrDefault("name", ""));
                            field.setType((String) m.getOrDefault("type", "string"));
                            field.setDescription((String) m.getOrDefault("description", ""));
                            field.setRequired(Boolean.TRUE.equals(m.get("required")));
                            return field;
                        }
                        return null;
                    })
                    .filter(java.util.Objects::nonNull)
                    .collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 列出技能目录下的所有文件（树形结构）
     */
    @GetMapping("/{folderName}/files")
    public Result<List<FileNodeDTO>> listFiles(@PathVariable String folderName) {
        return Result.success(skillService.listSkillFiles(folderName));
    }

    /**
     * 读取文件内容
     */
    @GetMapping("/{folderName}/files/content")
    public Result<String> readFile(@PathVariable String folderName,
                                   @RequestParam String path) {
        return Result.success(skillService.readFile(folderName, path));
    }

    /**
     * 保存文件内容
     */
    @PutMapping("/{folderName}/files/content")
    public Result<Void> saveFile(@PathVariable String folderName,
                                 @RequestBody Map<String, String> body) {
        skillService.saveFile(folderName, body.get("path"), body.get("content"));
        return Result.success("保存成功", null);
    }

    /**
     * 创建文件或目录
     */
    @PostMapping("/{folderName}/files")
    public Result<Void> createFile(@PathVariable String folderName,
                                   @RequestBody FileCreateDTO dto) {
        skillService.createFileOrDir(folderName, dto);
        return Result.success("创建成功", null);
    }

    /**
     * 删除文件或目录
     */
    @DeleteMapping("/{folderName}/files")
    public Result<Void> deleteFile(@PathVariable String folderName,
                                   @RequestParam String path) {
        skillService.deleteFile(folderName, path);
        return Result.success("删除成功", null);
    }

    // ==================== 版本管理 API ====================

    /**
     * 获取版本列表
     */
    @GetMapping("/{folderName}/versions")
    public Result<List<SkillVersionVO>> listVersions(@PathVariable String folderName) {
        return Result.success(skillVersionService.listVersions(folderName));
    }

    /**
     * 获取指定版本的 SKILL.md 内容
     */
    @GetMapping("/{folderName}/versions/{version}/content")
    public Result<String> getVersionContent(@PathVariable String folderName,
                                            @PathVariable int version) {
        return Result.success(skillVersionService.getVersionContent(folderName, version));
    }

    /**
     * 回滚到指定版本
     */
    @PostMapping("/{folderName}/versions/{version}/rollback")
    public Result<Void> rollbackVersion(@PathVariable String folderName,
                                        @PathVariable int version) {
        skillVersionService.rollback(folderName, version);
        return Result.success("回滚成功", null);
    }

    /**
     * 更新版本备注
     */
    @PutMapping("/{folderName}/versions/{version}/message")
    public Result<Void> updateVersionMessage(@PathVariable String folderName,
                                             @PathVariable int version,
                                             @RequestBody Map<String, String> body) {
        skillVersionService.updateVersionMessage(folderName, version, body.get("message"));
        return Result.success("更新成功", null);
    }

    // ==================== 技能-分类关联 API ====================

    /**
     * 设置技能的分类（传 categoryId 为 null 时取消分类）
     */
    @PutMapping("/{folderName}/category")
    public Result<Void> setSkillCategory(@PathVariable String folderName,
                                          @RequestBody Map<String, Object> body) {
        Object cidObj = body.get("categoryId");
        if (cidObj == null) {
            skillCategoryRepository.deleteBySkillFolderName(folderName);
        } else {
            Long categoryId = Long.valueOf(cidObj.toString());
            SkillCategory mapping = skillCategoryRepository.findBySkillFolderName(folderName)
                    .orElseGet(() -> {
                        SkillCategory sc = new SkillCategory();
                        sc.setSkillFolderName(folderName);
                        sc.onCreate();
                        return sc;
                    });
            mapping.setCategoryId(categoryId);
            skillCategoryRepository.save(mapping);
        }
        return Result.success("更新成功", null);
    }

    // ==================== 私有方法 ====================

    /**
     * 构建 VO：优先从缓存读取翻译（纯内存操作，不触发 LLM）
     */
    private SkillVO toVOWithCache(SkillDTO dto) {
        SkillVO vo = new SkillVO();
        vo.setFolderName(dto.getFolderName());
        vo.setName(dto.getName());
        vo.setDisplayName(dto.getDisplayName());
        vo.setDescription(dto.getDescription());
        vo.setCanGenerateSkill(dto.isCanGenerateSkill());
        // 仅翻译 displayName（name 为 kebab-case 标识符，不翻译；displayName 为空时 translatedDisplayName 留空）
        String displayName = dto.getDisplayName();
        vo.setTranslatedDisplayName(displayName != null && !displayName.isEmpty()
                ? translationService.getCachedTranslation(displayName) : null);
        vo.setTranslatedDescription(translationService.getCachedTranslation(dto.getDescription()));
        vo.setInputs(dto.getInputs());
        vo.setOutputs(dto.getOutputs());
        vo.setTags(tagService.getEntityTags("skill", dto.getFolderName()));
        vo.setCurrentVersion(skillVersionService.getCurrentVersion(dto.getFolderName()));
        return vo;
    }
}
