# CollabStateMachine.java

    package com.yumu.noveltranslator.domain.service;

    import com.yumu.noveltranslator.domain.model.CollabChapterTask;
    import com.yumu.noveltranslator.domain.model.CollabProject;
    import com.yumu.noveltranslator.enums.CollabProjectStatus;
    import com.yumu.noveltranslator.enums.ChapterTaskStatus;
    import org.springframework.stereotype.Component;

    /**
     * 协作翻译状态机
     * 验证项目和章节任务的状态转移是否合法，并提供驱动状态转移的方法。
     *
     * 状态转移应通过 {@link #transitionProject} / {@link #transitionChapter} 驱动，
     * 而非直接调用实体的 setStatus，以确保所有转移都经过合法性校验。
     */
    @Component
    public class CollabStateMachine {

        // ========== Validation-only methods (keep for backward compatibility) ==========

        /**
         * 验证项目状态转移是否合法
         */
        public void validateProjectTransition(CollabProjectStatus current, CollabProjectStatus target) {
            if (!current.canTransitionTo(target)) {
                throw new IllegalStateException(
                        "Invalid project state transition: " + current + " -> " + target);
            }
        }

        /**
         * 验证章节任务状态转移是否合法
         */
        public void validateChapterTransition(ChapterTaskStatus current, ChapterTaskStatus target) {
            if (!current.canTransitionTo(target)) {
                throw new IllegalStateException(
                        "Invalid chapter task state transition: " + current + " -> " + target);
            }
        }

        /**
         * 从字符串值验证项目状态转移
         */
        public void validateProjectTransition(String currentStr, String targetStr) {
            CollabProjectStatus current = CollabProjectStatus.fromValue(currentStr);
            CollabProjectStatus target = CollabProjectStatus.fromValue(targetStr);
            validateProjectTransition(current, target);
        }

        /**
         * 从字符串值验证章节状态转移
         */
        public void validateChapterTransition(String currentStr, String targetStr) {
            ChapterTaskStatus current = ChapterTaskStatus.fromValue(currentStr);
            ChapterTaskStatus target = ChapterTaskStatus.fromValue(targetStr);
            validateChapterTransition(current, target);
        }

        // ========== Driving methods (validate + set) ==========

        /**
         * 驱动项目状态转移：先校验转移合法性，再更新项目实体的 status 字段。
         * 这是修改 CollabProject 状态的唯一正确方式。
         *
         * @param project 项目实体
         * @param targetStatus 目标状态
         */
        public void transitionProject(CollabProject project, CollabProjectStatus targetStatus) {
            CollabProjectStatus current = CollabProjectStatus.fromValue(project.getStatus());
            validateProjectTransition(current, targetStatus);
            project.setStatus(targetStatus.getValue());
        }

        /**
         * 驱动项目状态转移（字符串重载）。
         */
        public void transitionProject(CollabProject project, String targetStatusStr) {
            CollabProjectStatus current = CollabProjectStatus.fromValue(project.getStatus());
            CollabProjectStatus target = CollabProjectStatus.fromValue(targetStatusStr);
            transitionProject(project, target);
        }

        /**
         * 驱动章节任务状态转移：先校验转移合法性，再更新章节实体的 status 字段。
         * 这是修改 CollabChapterTask 状态的唯一正确方式。
         *
         * @param chapter 章节任务实体
         * @param targetStatus 目标状态
         */
        public void transitionChapter(CollabChapterTask chapter, ChapterTaskStatus targetStatus) {
            ChapterTaskStatus current = ChapterTaskStatus.fromValue(chapter.getStatus());
            validateChapterTransition(current, targetStatus);
            chapter.setStatus(targetStatus.getValue());
        }

        /**
         * 驱动章节任务状态转移（字符串重载）。
         */
        public void transitionChapter(CollabChapterTask chapter, String targetStatusStr) {
            ChapterTaskStatus current = ChapterTaskStatus.fromValue(chapter.getStatus());
            ChapterTaskStatus target = ChapterTaskStatus.fromValue(targetStatusStr);
            transitionChapter(chapter, target);
        }
    }