package com.ningdatech.pmapi.common.statemachine.action;

import com.ningdatech.pmapi.common.constant.StateMachineConst;
import com.ningdatech.pmapi.common.statemachine.builder.ProjectDeclareStateMachineBuilder;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;

/**
 * 项目申报状态机action集合类
 *
 * @author CMM
 * @since 2023/02/08 13:48
 */
@Slf4j
@WithStateMachine(id = ProjectDeclareStateMachineBuilder.MACHINEID_TO)
public class ProjectDeclareAction {

    private static final String PROJECT_DECLARE = StateMachineConst.PROJECT_DECLARE;

    @OnTransition(source = "UNDER_INTERNAL_AUDIT", target = "PENDING_PREQUALIFICATION")
    public void UNDER_INTERNAL_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PENDING_PREQUALIFICATION.getCode());
    }

    @OnTransition(source = "UNDER_INTERNAL_AUDIT", target = "UNDER_INTERNAL_AUDIT_NOT_PASS")
    public void UNDER_INTERNAL_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.UNDER_INTERNAL_AUDIT_NOT_PASS.getCode());
    }

    @OnTransition(source = "UNDER_INTERNAL_AUDIT", target = "TO_BE_DECLARED")
    public void UNDER_INTERNAL_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.TO_BE_DECLARED.getCode());
    }


    @OnTransition(source = "PENDING_PREQUALIFICATION", target = "PENDING_PREQUALIFICATION_CHOICE")
    public void PRELIMINARY_REVIEW_DECLARE(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PENDING_PREQUALIFICATION_CHOICE.getCode());
    }

    @OnTransition(source = "PENDING_PREQUALIFICATION", target = "UNDER_INTERNAL_AUDIT")
    public void PENDING_PREQUALIFICATION_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.UNDER_INTERNAL_AUDIT.getCode());
    }


    @OnTransition(source = "JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS", target = "PRE_APPLYING")
    public void PROVINCIAL_DEPARTMENT_REVIEW_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PRE_APPLYING.getCode());
    }

    @OnTransition(source = "JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS", target = "THE_JOINT_REVIEW_OF_PROVINCIAL_DEPARTMENTS_FAILED")
    public void PROVINCIAL_DEPARTMENT_REVIEW_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.THE_JOINT_REVIEW_OF_PROVINCIAL_DEPARTMENTS_FAILED.getCode());
    }

    @OnTransition(source = "JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS", target = "PENDING_PREQUALIFICATION")
    public void JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PENDING_PREQUALIFICATION.getCode());
    }


    @OnTransition(source = "PRE_APPLYING", target = "DEPARTMENT_JOINT_REVIEW")
    public void PRELIMINARY_REVIEW_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW.getCode());
    }

    @OnTransition(source = "PRE_APPLYING", target = "PREQUALIFICATION_FAILED")
    public void PRELIMINARY_REVIEW_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PREQUALIFICATION_FAILED.getCode());
    }

    @OnTransition(source = "PRE_APPLYING", target = "PENDING_PREQUALIFICATION_CHOICE")
    public void PRE_APPLYING_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PENDING_PREQUALIFICATION_CHOICE.getCode());
    }


    @OnTransition(source = "DEPARTMENT_JOINT_REVIEW", target = "IN_THE_ANNUAL_PLAN")
    public void DEPARTMENT_UNITED_REVIEW_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.IN_THE_ANNUAL_PLAN.getCode());
    }

    @OnTransition(source = "DEPARTMENT_JOINT_REVIEW", target = "DEPARTMENT_JOINT_REVIEW_FAILED")
    public void DEPARTMENT_UNITED_REVIEW_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW_FAILED.getCode());
    }

    @OnTransition(source = "DEPARTMENT_JOINT_REVIEW", target = "PRE_APPLYING")
    public void DEPARTMENT_JOINT_REVIEW_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PRE_APPLYING.getCode());
    }


    @OnTransition(source = "IN_THE_ANNUAL_PLAN", target = "PLAN_TO_BE_DECLARED")
    public void ANNUAL_PLAN_PROJECT_OPEN_PLAN_DECLARE(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PLAN_TO_BE_DECLARED.getCode());
    }

    @OnTransition(source = "IN_THE_ANNUAL_PLAN", target = "BE_SUSPENDED")
    public void ANNUAL_PLAN_SUSPEND(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.BE_SUSPENDED.getCode());
    }

    @OnTransition(source = "IN_THE_ANNUAL_PLAN", target = "DEPARTMENT_JOINT_REVIEW")
    public void IN_THE_ANNUAL_PLAN_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW.getCode());
    }


    @OnTransition(source = "PLAN_TO_BE_DECLARED", target = "SCHEME_UNDER_REVIEW")
    public void DECLARE_PLAN(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.SCHEME_UNDER_REVIEW.getCode());
    }

    @OnTransition(source = "PLAN_TO_BE_DECLARED", target = "IN_THE_ANNUAL_PLAN")
    public void PLAN_TO_DECLARE_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.IN_THE_ANNUAL_PLAN.getCode());
    }


    @OnTransition(source = "SCHEME_UNDER_REVIEW", target = "TO_BE_APPROVED")
    public void PLAN_REVIEW_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.TO_BE_APPROVED.getCode());
    }

    @OnTransition(source = "SCHEME_UNDER_REVIEW", target = "SCHEME_REVIEW_FAILED")
    public void PLAN_REVIEW_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.SCHEME_REVIEW_FAILED.getCode());
    }

    @OnTransition(source = "SCHEME_UNDER_REVIEW", target = "PLAN_TO_BE_DECLARED")
    public void SCHEME_UNDER_REVIEW_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.PLAN_TO_BE_DECLARED.getCode());
    }


    @OnTransition(source = "TO_BE_APPROVED", target = "TO_BE_PURCHASED")
    public void PROJECT_APPROVAL(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        // 待立项批复批复后，项目一级状态变更为已立项
        project.setStage(ProjectStatusEnum.PROJECT_APPROVED.getCode());
        project.setStatus(ProjectStatusEnum.TO_BE_PURCHASED.getCode());
    }

    @OnTransition(source = "TO_BE_APPROVED", target = "SCHEME_UNDER_REVIEW")
    public void TO_BE_APPROVED_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.SCHEME_UNDER_REVIEW.getCode());
    }


    @OnTransition(source = "TO_BE_PURCHASED", target = "UNDER_CONSTRUCTION")
    public void PURCHASE_PUT_ON_RECORD(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.UNDER_CONSTRUCTION.getCode());
    }

    @OnTransition(source = "TO_BE_PURCHASED", target = "TO_BE_APPROVED")
    public void TO_BE_PURCHASED_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        // 待采购状态撤回后，项目一级状态回退到未立项
        project.setStage(ProjectStatusEnum.NOT_APPROVED.getCode());
        project.setStatus(ProjectStatusEnum.TO_BE_APPROVED.getCode());
    }


    @OnTransition(source = "UNDER_CONSTRUCTION", target = "TO_BE_FINALLY_INSPECTED")
    public void PRELIMINARY_ACCEPTANCE_PUT_ON_RECORD(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.UNDER_CONSTRUCTION.getCode());
    }

    @OnTransition(source = "UNDER_CONSTRUCTION", target = "TO_BE_PURCHASED")
    public void UNDER_CONSTRUCTION_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.TO_BE_PURCHASED.getCode());
    }


    @OnTransition(source = "TO_BE_FINALLY_INSPECTED", target = "FINAL_ACCEPTANCE_IS_UNDER_REVIEW")
    public void FINAL_ACCEPTANCE_APPLICATION(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.FINAL_ACCEPTANCE_IS_UNDER_REVIEW.getCode());
    }

    @OnTransition(source = "TO_BE_FINALLY_INSPECTED", target = "UNDER_CONSTRUCTION")
    public void TO_BE_FINALLY_INSPECTED_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.UNDER_CONSTRUCTION.getCode());
    }


    @OnTransition(source = "FINAL_ACCEPTANCE_IS_UNDER_REVIEW", target = "ARCHIVED")
    public void FINAL_ACCEPTANCE_PASS(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        // 终验审核通过后，项目一级状态变更为已归档
        project.setStage(ProjectStatusEnum.ARCHIVED.getCode());
        project.setStatus(ProjectStatusEnum.ACCEPTED.getCode());
    }

    @OnTransition(source = "FINAL_ACCEPTANCE_IS_UNDER_REVIEW", target = "FINAL_ACCEPTANCE_REVIEW_FAILED")
    public void FINAL_ACCEPTANCE_REJECT(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.FINAL_ACCEPTANCE_REVIEW_FAILED.getCode());
    }

    @OnTransition(source = "FINAL_ACCEPTANCE_IS_UNDER_REVIEW", target = "FINAL_ACCEPTANCE_IS_UNDER_REVIEW")
    public void FINAL_ACCEPTANCE_IS_UNDER_REVIEW_WITHDRAW(Message<ProjectStatusChangeEvent> message) {
        Project project = (Project) message.getHeaders().get(PROJECT_DECLARE);
        project.setStatus(ProjectStatusEnum.FINAL_ACCEPTANCE_IS_UNDER_REVIEW.getCode());
    }


    public class ProjectDeclareChoiceAction implements Action<ProjectStatusEnum, ProjectStatusChangeEvent> {

        @Override
        public void execute(StateContext<ProjectStatusEnum, ProjectStatusChangeEvent> stateContext) {
            log.info(String.valueOf(stateContext.getTarget().getId()));
            ProjectStatusEnum projectStatusEnum = stateContext.getTarget().getId();
            if (projectStatusEnum.equals(ProjectStatusEnum.PENDING_PREQUALIFICATION_CHOICE)) {
                Project project = stateContext.getMessage().getHeaders().get(PROJECT_DECLARE, Project.class);
                log.info("预审申报事件之前，项目的状态为:{}" + project.getStatus());
                if (StateMachineUtils.isCityProject(project) && StateMachineUtils.judgeDeclareAmount(project)) {
                    project.setStatus(ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS.getCode());
                } else {
                    project.setStatus(ProjectStatusEnum.PRE_APPLYING.getCode());
                }
            }
        }
    }
}
