package tech.easyflow.skill.mapper;

import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import tech.easyflow.skill.entity.Skill;

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

/**
 * Skill Mapper。
 */
public interface SkillMapper extends BaseMapper<Skill> {

    /**
     * 在租户边界内更新审批中的发布状态，并显式写入或清空审批实例 ID。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param publishStatus 发布状态
     * @param approvalInstanceId 当前审批实例 ID，可为空
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status=#{publishStatus}, "
            + "current_approval_instance_id=#{approvalInstanceId} "
            + "WHERE id=#{id} AND tenant_id=#{tenantId}")
    int updateApprovalState(@Param("id") BigInteger id,
                            @Param("tenantId") BigInteger tenantId,
                            @Param("publishStatus") String publishStatus,
                            @Param("approvalInstanceId") BigInteger approvalInstanceId);

    /**
     * 在租户边界内持久化已发布快照，并原子清空审批实例 ID。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param snapshot 已发布快照
     * @param publishedAt 发布时间
     * @param publishedBy 发布人
     * @param snapshotHash 快照哈希
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status='PUBLISHED', "
            + "published_snapshot_json=#{snapshot,typeHandler=com.mybatisflex.core.handler.FastjsonTypeHandler}, "
            + "published_at=#{publishedAt}, published_by=#{publishedBy}, "
            + "snapshot_hash=#{snapshotHash}, current_approval_instance_id=NULL "
            + "WHERE id=#{id} AND tenant_id=#{tenantId}")
    int publish(@Param("id") BigInteger id,
                @Param("tenantId") BigInteger tenantId,
                @Param("snapshot") Map<String, Object> snapshot,
                @Param("publishedAt") Date publishedAt,
                @Param("publishedBy") BigInteger publishedBy,
                @Param("snapshotHash") String snapshotHash);

    /**
     * 按当前审批实例原子发布 Skill，并保留已应用实例作为幂等账本。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param approvalInstanceId 审批实例 ID
     * @param snapshot 已发布快照
     * @param publishedAt 发布时间
     * @param publishedBy 发布人
     * @param snapshotHash 快照哈希
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status='PUBLISHED', "
            + "published_snapshot_json=#{snapshot,typeHandler=com.mybatisflex.core.handler.FastjsonTypeHandler}, "
            + "published_at=#{publishedAt}, published_by=#{publishedBy}, snapshot_hash=#{snapshotHash}, "
            + "current_approval_instance_id=#{approvalInstanceId} WHERE id=#{id} AND tenant_id=#{tenantId} "
            + "AND current_approval_instance_id=#{approvalInstanceId}")
    int publishApproved(@Param("id") BigInteger id,
                        @Param("tenantId") BigInteger tenantId,
                        @Param("approvalInstanceId") BigInteger approvalInstanceId,
                        @Param("snapshot") Map<String, Object> snapshot,
                        @Param("publishedAt") Date publishedAt,
                        @Param("publishedBy") BigInteger publishedBy,
                        @Param("snapshotHash") String snapshotHash);

    /**
     * 在租户边界内将 Skill 标记为下线，并清空审批实例 ID。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status='OFFLINE', current_approval_instance_id=NULL "
            + "WHERE id=#{id} AND tenant_id=#{tenantId}")
    int markOffline(@Param("id") BigInteger id, @Param("tenantId") BigInteger tenantId);

    /**
     * 按当前审批实例原子下线 Skill，并保留已应用实例作为幂等账本。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param approvalInstanceId 审批实例 ID
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status='OFFLINE', current_approval_instance_id=#{approvalInstanceId} "
            + "WHERE id=#{id} AND tenant_id=#{tenantId} AND current_approval_instance_id=#{approvalInstanceId}")
    int markOfflineApproved(@Param("id") BigInteger id,
                            @Param("tenantId") BigInteger tenantId,
                            @Param("approvalInstanceId") BigInteger approvalInstanceId);

    /**
     * 按当前审批实例恢复提交前状态并清空待审批实例。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param approvalInstanceId 审批实例 ID
     * @param publishStatus 恢复状态
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET publish_status=#{publishStatus}, current_approval_instance_id=NULL "
            + "WHERE id=#{id} AND tenant_id=#{tenantId} AND current_approval_instance_id=#{approvalInstanceId}")
    int restoreApprovalState(@Param("id") BigInteger id,
                             @Param("tenantId") BigInteger tenantId,
                             @Param("approvalInstanceId") BigInteger approvalInstanceId,
                             @Param("publishStatus") String publishStatus);

    /**
     * 无审计污染地回填迁移后缺失的包摘要，仅处理 package_hash 为空的旧记录。
     *
     * @param id Skill ID
     * @param tenantId 租户 ID
     * @param packageHash 包哈希
     * @return 更新行数
     */
    @Update("UPDATE tb_skill SET package_hash=#{packageHash}, modified=modified, modified_by=modified_by "
            + "WHERE id=#{id} AND tenant_id=#{tenantId} AND package_hash IS NULL")
    int backfillPackageHash(@Param("id") BigInteger id,
                            @Param("tenantId") BigInteger tenantId,
                            @Param("packageHash") String packageHash);

}
