package tech.easyflow.skill.service;

import com.mybatisflex.core.service.IService;
import tech.easyflow.skill.entity.Skill;
import tech.easyflow.skill.validation.SkillValidationResult;

import java.math.BigInteger;
import java.util.Map;

/**
 * Skill 业务服务。
 */
public interface SkillService extends IService<Skill> {

    /**
     * 获取 Skill 详情。
     *
     * @param id Skill ID
     * @return Skill 详情
     */
    Skill getDetail(BigInteger id);

    /**
     * 获取管理端详情，资源仅返回描述字段，不预加载全部文件正文。
     *
     * @param id Skill ID
     * @return Skill 管理详情
     */
    Skill getManagementDetail(BigInteger id);

    /**
     * 获取仅包含标准 Skill 包内容的授权详情。
     *
     * @param id Skill ID
     * @return Skill 包内容详情
     */
    Skill getPackageDetail(BigInteger id);

    /**
     * 保存 Skill 草稿。
     *
     * @param skill Skill 草稿
     * @return 保存后的 Skill
     */
    Skill saveDraft(Skill skill);

    /**
     * 更新 Skill 草稿。
     *
     * @param skill Skill 草稿
     * @return 更新后的 Skill
     */
    Skill updateDraft(Skill skill);

    /**
     * 覆盖导入内容，并在锁定目标行后再次确认目标仍为草稿。
     *
     * @param skill 导入后的 Skill 草稿
     * @return 更新后的 Skill
     */
    Skill overwriteImportedDraft(Skill skill);

    /**
     * 按客户端读取到的 SKILL.md 内容 hash 原子更新草稿，防止并发覆盖。
     *
     * @param skill Skill 草稿
     * @param expectedSkillContentHash 客户端读取到的 SKILL.md SHA-256
     * @return 更新后的 Skill
     */
    Skill updateDraftIfContentMatches(Skill skill, String expectedSkillContentHash);

    /**
     * 复制一个可读 Skill 为当前用户拥有的新草稿。
     *
     * @param sourceId 源 Skill ID
     * @param name 新 Skill 标准名称
     * @param displayName 新 Skill 展示名称
     * @param categoryId 目标分类 ID，可为空
     * @return 新建的 Skill 草稿
     */
    Skill copyDraft(BigInteger sourceId, String name, String displayName, BigInteger categoryId);

    /**
     * 对当前标准 Skill 包执行校验。
     *
     * @param id Skill ID
     * @param publishValidation 是否执行发布级完整校验
     * @return 结构化校验结果
     */
    SkillValidationResult validateSkill(BigInteger id, boolean publishValidation);

    /**
     * 在文件级修改后重新计算包 hash。
     *
     * @param id Skill ID
     */
    void refreshPackageState(BigInteger id);

    /**
     * 构建发布快照。
     *
     * @param skill Skill 草稿
     * @return 发布快照
     */
    Map<String, Object> buildPublishSnapshot(Skill skill);

    /**
     * 构建审批冻结用的内容与平台 Tool 组合快照。
     *
     * @param skill Skill 草稿
     * @return 组合发布候选快照
     */
    Map<String, Object> buildApprovalSnapshot(Skill skill);

    /**
     * 从组合发布候选中提取保持标准包语义的内容快照。
     *
     * @param approvalSnapshot 组合发布候选
     * @return 标准 Skill 内容快照
     */
    Map<String, Object> extractContentSnapshot(Map<String, Object> approvalSnapshot);

    /**
     * 从组合发布候选中提取平台 Tool 快照。
     *
     * @param approvalSnapshot 组合发布候选
     * @return 平台 Tool 快照
     */
    Map<String, Object> extractToolBindingsSnapshot(Map<String, Object> approvalSnapshot);

    /**
     * 校验发布快照中的哈希与实际内容一致。
     *
     * @param snapshot 发布快照
     */
    void assertSnapshotHash(Map<String, Object> snapshot);

    /**
     * 校验已发布 Skill 的内容、平台 Tool 与组合 hash。
     *
     * @param skill 已发布 Skill
     */
    void assertPublishedAggregateHash(Skill skill);

    /**
     * 校验 Skill 没有被 Agent 草稿或有效发布快照引用。
     *
     * @param skillId Skill ID
     */
    void assertNoActiveReferences(BigInteger skillId);

    /**
     * 构建删除审批使用的最小治理快照。
     *
     * @param skill Skill
     * @return 不含 SKILL.md 正文和资源内容的治理快照
     */
    Map<String, Object> buildGovernanceSnapshot(Skill skill);

    /**
     * 为发布候选或已发布快照中的每个二进制资源增加一份持有引用。
     *
     * @param snapshot Skill 发布快照
     */
    void retainSnapshotContents(Map<String, Object> snapshot);

    /**
     * 释放发布候选或已发布快照中的每个二进制资源持有引用。
     *
     * @param snapshot Skill 发布快照
     */
    void releaseSnapshotContents(Map<String, Object> snapshot);

    /**
     * 从发布快照还原 Skill。
     *
     * @param snapshot 发布快照
     * @return Skill
     */
    Skill fromSnapshot(Map<String, Object> snapshot);

    /**
     * 删除草稿或已下线的 Skill 聚合。
     *
     * <p>已发布记录必须先下线，任何审批中记录都不能通过此普通仓储入口删除。</p>
     *
     * @param id Skill ID
     * @throws tech.easyflow.common.web.exceptions.BusinessException Skill 不存在、无权限或当前状态不可删除
     */
    void removeAggregate(BigInteger id);

    /**
     * 由统一发布生命周期删除 Skill 聚合。
     *
     * <p>该入口允许删除审批已经进入 {@code DELETE_PENDING} 的记录，也兼容未配置审批流时
     * 直接删除草稿或已下线记录。普通仓储删除必须使用 {@link #removeAggregate(BigInteger)}。</p>
     *
     * @param id Skill ID
     * @throws tech.easyflow.common.web.exceptions.BusinessException Skill 不存在、无权限或当前状态不可删除
     */
    void removeLifecycleAggregate(BigInteger id);
}
