BattleEngineConfiguration.kt

package io.github.lishangbu.avalon.game.battle.engine.adapter.spring

import io.github.lishangbu.avalon.game.battle.engine.adapter.memory.session.InMemoryBattleSessionGateway
import io.github.lishangbu.avalon.game.battle.engine.adapter.memory.store.InMemoryBattleSessionStore
import io.github.lishangbu.avalon.game.battle.engine.application.BattleChoiceResolver
import io.github.lishangbu.avalon.game.battle.engine.application.BattleEngineService
import io.github.lishangbu.avalon.game.battle.engine.application.BattleSettlementPlanner
import io.github.lishangbu.avalon.game.battle.engine.application.DefaultBattleEngineService
import io.github.lishangbu.avalon.game.battle.engine.application.StandardBattleSettlementPlanner
import io.github.lishangbu.avalon.game.battle.engine.application.WildBattleSettlementPlanner
import io.github.lishangbu.avalon.game.battle.engine.application.gateway.BattleSessionGateway
import io.github.lishangbu.avalon.game.battle.engine.core.capture.CaptureFormulaService
import io.github.lishangbu.avalon.game.battle.engine.core.capture.CaptureRandomSource
import io.github.lishangbu.avalon.game.battle.engine.core.capture.DefaultCaptureActionResolver
import io.github.lishangbu.avalon.game.battle.engine.core.capture.DefaultCaptureFormulaService
import io.github.lishangbu.avalon.game.battle.engine.core.capture.DefaultCaptureRandomSource
import io.github.lishangbu.avalon.game.battle.engine.core.capture.SnapshotCaptureFormulaInputResolver
import io.github.lishangbu.avalon.game.battle.engine.core.registry.ActionExecutorRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.registry.ConditionInterpreterRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.registry.memory.StandardActionExecutorRegistryFactory
import io.github.lishangbu.avalon.game.battle.engine.core.registry.memory.StandardConditionInterpreterRegistryFactory
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.DefaultHookRuleProcessor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.HookRuleProcessor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.apply.DefaultMutationApplier
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.apply.MutationApplier
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.AddVolatileBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.ApplyConditionBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleFlowEngine
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleFlowPhaseProcessor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleHitResolutionPolicy
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveAccuracyEvasionPhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveAfterMovePhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveBeforeDamagePhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveCriticalHitPhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveHitHooksPhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveHitResolutionStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMovePowerDamagePhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMovePreHitPhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveResolutionPipeline
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveResolutionStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveSpecialHitPhaseStep
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMoveSpecialHitRuleResolver
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleMutationInterceptorChain
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleTypeEffectivenessResolver
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BoostBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.ChangeTypeBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.ClearBoostsBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.ConsumeItemBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DamageBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DefaultBattleFlowEngine
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DefaultBattleFlowPhaseProcessor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DefaultBattleHitResolutionPolicy
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DefaultBattleMoveResolutionPipeline
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.DefaultBattleMutationInterceptorChain
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.HealBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.NoopBattleTypeEffectivenessResolver
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.RemoveConditionBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.RemoveStatusBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.RemoveVolatileBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.RestorePpBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.SetStatusBattleMutationInterceptor
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionActionExecutionSupport
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionActionHandlerRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionActionSortingStrategy
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionBattleLogProjector
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionBeforeTurnStep
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionCaptureActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionCaptureChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionChoiceHandlerRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionCommandFactory
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionEventPublisher
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionFactory
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionItemActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionItemChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionMoveActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionMoveChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionProjector
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionQueuedActionExecutionStep
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionResourceLedgerProjector
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionRunActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionRunChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionStructuredEventProjector
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionSwitchActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionSwitchChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionTurnAdvanceStep
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionTurnPipeline
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionTurnStep
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionTurnValidationStep
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionWaitActionHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.BattleSessionWaitChoiceHandler
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultBattleSessionActionSortingStrategy
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultBattleSessionCommandFactory
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultBattleSessionEventPublisher
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultBattleSessionFactory
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultBattleSessionTurnPipeline
import io.github.lishangbu.avalon.game.battle.engine.core.session.DefaultReplacementStrategy
import io.github.lishangbu.avalon.game.battle.engine.core.session.InMemoryBattleSessionActionHandlerRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.session.InMemoryBattleSessionChoiceHandlerRegistry
import io.github.lishangbu.avalon.game.battle.engine.core.session.ReplacementStrategy
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionCaptureChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionItemChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionMoveChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionRunChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionTargetChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionTurnReadySpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.BattleSessionUnitChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionCaptureChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionItemChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionMoveChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionRunChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionTargetChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionTurnReadySpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.specification.DefaultBattleSessionUnitChoiceSpecification
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.BattleSessionAvailableTargetResolver
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.BattleSessionTargetModeResolver
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.BattleSessionTargetQueryService
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.DefaultBattleSessionAvailableTargetResolver
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.DefaultBattleSessionTargetModeResolver
import io.github.lishangbu.avalon.game.battle.engine.core.session.target.DefaultBattleSessionTargetQueryService
import io.github.lishangbu.avalon.game.battle.engine.spi.ai.BattleAiChoiceProvider
import io.github.lishangbu.avalon.game.battle.engine.spi.capture.CaptureActionResolver
import io.github.lishangbu.avalon.game.battle.engine.spi.capture.CaptureFormulaInputResolver
import io.github.lishangbu.avalon.game.battle.engine.spi.effect.EffectDefinitionRepository
import io.github.lishangbu.avalon.game.battle.engine.spi.store.BattleSessionStore
import io.github.lishangbu.avalon.game.calculator.capture.CaptureRateCalculator
import io.github.lishangbu.avalon.game.calculator.capture.DefaultCaptureRateCalculator
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

/**
 * `avalon-game-battle-engine` 默认装配。
 */
@Configuration(proxyBeanMethods = false)
class BattleEngineConfiguration {
    @Bean
    @ConditionalOnMissingBean
    fun captureRandomSource(): CaptureRandomSource = DefaultCaptureRandomSource()

    @Bean
    @ConditionalOnMissingBean
    fun captureRateCalculator(): CaptureRateCalculator = DefaultCaptureRateCalculator()

    @Bean
    @ConditionalOnMissingBean
    fun captureFormulaService(
        captureRandomSource: CaptureRandomSource,
        captureRateCalculator: CaptureRateCalculator,
    ): CaptureFormulaService = DefaultCaptureFormulaService(captureRandomSource, captureRateCalculator)

    @Bean
    @ConditionalOnMissingBean(CaptureFormulaInputResolver::class)
    fun captureFormulaInputResolver(): CaptureFormulaInputResolver = SnapshotCaptureFormulaInputResolver()

    @Bean
    @ConditionalOnMissingBean(CaptureActionResolver::class)
    fun captureActionResolver(
        captureFormulaInputResolver: CaptureFormulaInputResolver,
        captureFormulaService: CaptureFormulaService,
    ): CaptureActionResolver = DefaultCaptureActionResolver(captureFormulaInputResolver, captureFormulaService)

    @Bean
    @ConditionalOnMissingBean
    fun conditionInterpreterRegistry(): ConditionInterpreterRegistry = StandardConditionInterpreterRegistryFactory.create()

    @Bean
    @ConditionalOnMissingBean
    fun actionExecutorRegistry(): ActionExecutorRegistry = StandardActionExecutorRegistryFactory.create()

    @Bean
    @ConditionalOnMissingBean
    fun hookRuleProcessor(
        conditionInterpreterRegistry: ConditionInterpreterRegistry,
        actionExecutorRegistry: ActionExecutorRegistry,
    ): HookRuleProcessor =
        DefaultHookRuleProcessor(
            conditionInterpreterRegistry = conditionInterpreterRegistry,
            actionExecutorRegistry = actionExecutorRegistry,
        )

    @Bean
    @ConditionalOnMissingBean
    fun mutationApplier(): MutationApplier = DefaultMutationApplier()

    @Bean
    @ConditionalOnMissingBean
    fun replacementStrategy(): ReplacementStrategy = DefaultReplacementStrategy()

    @Bean
    @ConditionalOnMissingBean(SetStatusBattleMutationInterceptor::class)
    fun setStatusBattleMutationInterceptor(): SetStatusBattleMutationInterceptor = SetStatusBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(RemoveStatusBattleMutationInterceptor::class)
    fun removeStatusBattleMutationInterceptor(): RemoveStatusBattleMutationInterceptor = RemoveStatusBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(AddVolatileBattleMutationInterceptor::class)
    fun addVolatileBattleMutationInterceptor(): AddVolatileBattleMutationInterceptor = AddVolatileBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(RemoveVolatileBattleMutationInterceptor::class)
    fun removeVolatileBattleMutationInterceptor(): RemoveVolatileBattleMutationInterceptor = RemoveVolatileBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(ApplyConditionBattleMutationInterceptor::class)
    fun applyConditionBattleMutationInterceptor(): ApplyConditionBattleMutationInterceptor = ApplyConditionBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(ConsumeItemBattleMutationInterceptor::class)
    fun consumeItemBattleMutationInterceptor(): ConsumeItemBattleMutationInterceptor = ConsumeItemBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(DamageBattleMutationInterceptor::class)
    fun damageBattleMutationInterceptor(): DamageBattleMutationInterceptor = DamageBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(HealBattleMutationInterceptor::class)
    fun healBattleMutationInterceptor(): HealBattleMutationInterceptor = HealBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(BoostBattleMutationInterceptor::class)
    fun boostBattleMutationInterceptor(): BoostBattleMutationInterceptor = BoostBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(ClearBoostsBattleMutationInterceptor::class)
    fun clearBoostsBattleMutationInterceptor(): ClearBoostsBattleMutationInterceptor = ClearBoostsBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(RemoveConditionBattleMutationInterceptor::class)
    fun removeConditionBattleMutationInterceptor(): RemoveConditionBattleMutationInterceptor = RemoveConditionBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(RestorePpBattleMutationInterceptor::class)
    fun restorePpBattleMutationInterceptor(): RestorePpBattleMutationInterceptor = RestorePpBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(ChangeTypeBattleMutationInterceptor::class)
    fun changeTypeBattleMutationInterceptor(): ChangeTypeBattleMutationInterceptor = ChangeTypeBattleMutationInterceptor()

    @Bean
    @ConditionalOnMissingBean(BattleMutationInterceptorChain::class)
    fun battleMutationInterceptorChain(
        interceptors: List<BattleMutationInterceptor>,
    ): BattleMutationInterceptorChain = DefaultBattleMutationInterceptorChain(interceptors)

    @Bean
    @ConditionalOnMissingBean(BattleFlowPhaseProcessor::class)
    fun battleFlowPhaseProcessor(
        effectDefinitionRepository: EffectDefinitionRepository,
        hookRuleProcessor: HookRuleProcessor,
        mutationApplier: MutationApplier,
        battleMutationInterceptorChain: BattleMutationInterceptorChain,
    ): BattleFlowPhaseProcessor =
        DefaultBattleFlowPhaseProcessor(
            effectRepository = effectDefinitionRepository,
            hookRuleProcessor = hookRuleProcessor,
            mutationApplier = mutationApplier,
            mutationInterceptorChain = battleMutationInterceptorChain,
        )

    @Bean
    @ConditionalOnMissingBean(BattleHitResolutionPolicy::class)
    fun battleHitResolutionPolicy(): BattleHitResolutionPolicy = DefaultBattleHitResolutionPolicy()

    @Bean
    @ConditionalOnMissingBean(BattleTypeEffectivenessResolver::class)
    fun battleTypeEffectivenessResolver(): BattleTypeEffectivenessResolver = NoopBattleTypeEffectivenessResolver

    @Bean
    @ConditionalOnMissingBean(BattleMovePreHitPhaseStep::class)
    fun battleMovePreHitPhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMovePreHitPhaseStep = BattleMovePreHitPhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMoveAccuracyEvasionPhaseStep::class)
    fun battleMoveAccuracyEvasionPhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMoveAccuracyEvasionPhaseStep = BattleMoveAccuracyEvasionPhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMoveSpecialHitRuleResolver::class)
    fun battleMoveSpecialHitRuleResolver(): BattleMoveSpecialHitRuleResolver = BattleMoveSpecialHitRuleResolver()

    @Bean
    @ConditionalOnMissingBean(BattleMoveSpecialHitPhaseStep::class)
    fun battleMoveSpecialHitPhaseStep(
        battleMoveSpecialHitRuleResolver: BattleMoveSpecialHitRuleResolver,
    ): BattleMoveSpecialHitPhaseStep = BattleMoveSpecialHitPhaseStep(battleMoveSpecialHitRuleResolver)

    @Bean
    @ConditionalOnMissingBean(BattleMoveHitResolutionStep::class)
    fun battleMoveHitResolutionStep(
        battleHitResolutionPolicy: BattleHitResolutionPolicy,
    ): BattleMoveHitResolutionStep = BattleMoveHitResolutionStep(battleHitResolutionPolicy)

    @Bean
    @ConditionalOnMissingBean(BattleMoveCriticalHitPhaseStep::class)
    fun battleMoveCriticalHitPhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMoveCriticalHitPhaseStep = BattleMoveCriticalHitPhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMoveBeforeDamagePhaseStep::class)
    fun battleMoveBeforeDamagePhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMoveBeforeDamagePhaseStep = BattleMoveBeforeDamagePhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMovePowerDamagePhaseStep::class)
    fun battleMovePowerDamagePhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
        battleTypeEffectivenessResolver: BattleTypeEffectivenessResolver,
    ): BattleMovePowerDamagePhaseStep = BattleMovePowerDamagePhaseStep(battleFlowPhaseProcessor, battleTypeEffectivenessResolver)

    @Bean
    @ConditionalOnMissingBean(BattleMoveHitHooksPhaseStep::class)
    fun battleMoveHitHooksPhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMoveHitHooksPhaseStep = BattleMoveHitHooksPhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMoveAfterMovePhaseStep::class)
    fun battleMoveAfterMovePhaseStep(
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
    ): BattleMoveAfterMovePhaseStep = BattleMoveAfterMovePhaseStep(battleFlowPhaseProcessor)

    @Bean
    @ConditionalOnMissingBean(BattleMoveResolutionPipeline::class)
    fun battleMoveResolutionPipeline(
        steps: List<BattleMoveResolutionStep>,
    ): BattleMoveResolutionPipeline = DefaultBattleMoveResolutionPipeline(steps)

    @Bean
    @ConditionalOnMissingBean(BattleFlowEngine::class)
    fun battleFlowEngine(
        effectDefinitionRepository: EffectDefinitionRepository,
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
        battleMoveResolutionPipeline: BattleMoveResolutionPipeline,
    ): BattleFlowEngine =
        DefaultBattleFlowEngine(
            effectRepository = effectDefinitionRepository,
            phaseProcessor = battleFlowPhaseProcessor,
            moveResolutionPipeline = battleMoveResolutionPipeline,
        )

    @Bean
    @ConditionalOnMissingBean(BattleSessionActionSortingStrategy::class)
    fun battleSessionActionSortingStrategy(): BattleSessionActionSortingStrategy = DefaultBattleSessionActionSortingStrategy()

    @Bean
    @ConditionalOnMissingBean(BattleSessionBattleLogProjector::class)
    fun battleSessionBattleLogProjector(): BattleSessionBattleLogProjector = BattleSessionBattleLogProjector()

    @Bean
    @ConditionalOnMissingBean(BattleSessionStructuredEventProjector::class)
    fun battleSessionStructuredEventProjector(): BattleSessionStructuredEventProjector = BattleSessionStructuredEventProjector()

    @Bean
    @ConditionalOnMissingBean(BattleSessionResourceLedgerProjector::class)
    fun battleSessionResourceLedgerProjector(): BattleSessionResourceLedgerProjector = BattleSessionResourceLedgerProjector()

    @Bean
    @ConditionalOnMissingBean(BattleSessionEventPublisher::class)
    fun battleSessionEventPublisher(
        projectors: List<BattleSessionProjector>,
    ): BattleSessionEventPublisher = DefaultBattleSessionEventPublisher(projectors)

    @Bean
    @ConditionalOnMissingBean(BattleSessionTargetModeResolver::class)
    fun battleSessionTargetModeResolver(
        effectDefinitionRepository: EffectDefinitionRepository,
    ): BattleSessionTargetModeResolver = DefaultBattleSessionTargetModeResolver(effectDefinitionRepository)

    @Bean
    @ConditionalOnMissingBean(BattleSessionAvailableTargetResolver::class)
    fun battleSessionAvailableTargetResolver(): BattleSessionAvailableTargetResolver = DefaultBattleSessionAvailableTargetResolver()

    @Bean
    @ConditionalOnMissingBean(BattleSessionTargetQueryService::class)
    fun battleSessionTargetQueryService(
        battleSessionTargetModeResolver: BattleSessionTargetModeResolver,
        battleSessionAvailableTargetResolver: BattleSessionAvailableTargetResolver,
    ): BattleSessionTargetQueryService =
        DefaultBattleSessionTargetQueryService(
            targetModeResolver = battleSessionTargetModeResolver,
            availableTargetResolver = battleSessionAvailableTargetResolver,
        )

    @Bean
    @ConditionalOnMissingBean(BattleSessionTurnReadySpecification::class)
    fun battleSessionTurnReadySpecification(): BattleSessionTurnReadySpecification = DefaultBattleSessionTurnReadySpecification()

    @Bean
    @ConditionalOnMissingBean(BattleSessionUnitChoiceSpecification::class)
    fun battleSessionUnitChoiceSpecification(): BattleSessionUnitChoiceSpecification = DefaultBattleSessionUnitChoiceSpecification()

    @Bean
    @ConditionalOnMissingBean(BattleSessionRunChoiceSpecification::class)
    fun battleSessionRunChoiceSpecification(): BattleSessionRunChoiceSpecification = DefaultBattleSessionRunChoiceSpecification()

    @Bean
    @ConditionalOnMissingBean(BattleSessionTargetChoiceSpecification::class)
    fun battleSessionTargetChoiceSpecification(
        battleSessionTargetQueryService: BattleSessionTargetQueryService,
    ): BattleSessionTargetChoiceSpecification = DefaultBattleSessionTargetChoiceSpecification(battleSessionTargetQueryService)

    @Bean
    @ConditionalOnMissingBean(BattleSessionCaptureChoiceSpecification::class)
    fun battleSessionCaptureChoiceSpecification(): BattleSessionCaptureChoiceSpecification = DefaultBattleSessionCaptureChoiceSpecification()

    @Bean
    @ConditionalOnMissingBean(BattleSessionMoveChoiceSpecification::class)
    fun battleSessionMoveChoiceSpecification(
        effectDefinitionRepository: EffectDefinitionRepository,
    ): BattleSessionMoveChoiceSpecification = DefaultBattleSessionMoveChoiceSpecification(effectDefinitionRepository)

    @Bean
    @ConditionalOnMissingBean(BattleSessionItemChoiceSpecification::class)
    fun battleSessionItemChoiceSpecification(
        effectDefinitionRepository: EffectDefinitionRepository,
    ): BattleSessionItemChoiceSpecification = DefaultBattleSessionItemChoiceSpecification(effectDefinitionRepository)

    @Bean
    @ConditionalOnMissingBean
    fun battleSessionActionExecutionSupport(): BattleSessionActionExecutionSupport = BattleSessionActionExecutionSupport()

    @Bean
    @ConditionalOnMissingBean(BattleSessionCommandFactory::class)
    fun battleSessionCommandFactory(): BattleSessionCommandFactory = DefaultBattleSessionCommandFactory()

    @Bean
    @ConditionalOnMissingBean(BattleSessionMoveChoiceHandler::class)
    fun battleSessionMoveChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionMoveChoiceHandler = BattleSessionMoveChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionSwitchChoiceHandler::class)
    fun battleSessionSwitchChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionSwitchChoiceHandler = BattleSessionSwitchChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionItemChoiceHandler::class)
    fun battleSessionItemChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionItemChoiceHandler = BattleSessionItemChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionCaptureChoiceHandler::class)
    fun battleSessionCaptureChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionCaptureChoiceHandler = BattleSessionCaptureChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionRunChoiceHandler::class)
    fun battleSessionRunChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionRunChoiceHandler = BattleSessionRunChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionWaitChoiceHandler::class)
    fun battleSessionWaitChoiceHandler(
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionWaitChoiceHandler = BattleSessionWaitChoiceHandler(battleSessionCommandFactory)

    @Bean
    @ConditionalOnMissingBean(BattleSessionChoiceHandlerRegistry::class)
    fun battleSessionChoiceHandlerRegistry(
        battleSessionCommandFactory: BattleSessionCommandFactory,
        handlers: List<BattleSessionChoiceHandler>,
    ): BattleSessionChoiceHandlerRegistry = InMemoryBattleSessionChoiceHandlerRegistry(handlers)

    @Bean
    @ConditionalOnMissingBean(BattleSessionMoveActionHandler::class)
    fun battleSessionMoveActionHandler(
        battleSessionActionExecutionSupport: BattleSessionActionExecutionSupport,
    ): BattleSessionMoveActionHandler = BattleSessionMoveActionHandler(battleSessionActionExecutionSupport)

    @Bean
    @ConditionalOnMissingBean(BattleSessionSwitchActionHandler::class)
    fun battleSessionSwitchActionHandler(
        battleSessionActionExecutionSupport: BattleSessionActionExecutionSupport,
    ): BattleSessionSwitchActionHandler = BattleSessionSwitchActionHandler(battleSessionActionExecutionSupport)

    @Bean
    @ConditionalOnMissingBean(BattleSessionItemActionHandler::class)
    fun battleSessionItemActionHandler(
        battleSessionActionExecutionSupport: BattleSessionActionExecutionSupport,
    ): BattleSessionItemActionHandler = BattleSessionItemActionHandler(battleSessionActionExecutionSupport)

    @Bean
    @ConditionalOnMissingBean(BattleSessionCaptureActionHandler::class)
    fun battleSessionCaptureActionHandler(): BattleSessionCaptureActionHandler = BattleSessionCaptureActionHandler()

    @Bean
    @ConditionalOnMissingBean(BattleSessionRunActionHandler::class)
    fun battleSessionRunActionHandler(
        battleSessionActionExecutionSupport: BattleSessionActionExecutionSupport,
    ): BattleSessionRunActionHandler = BattleSessionRunActionHandler(battleSessionActionExecutionSupport)

    @Bean
    @ConditionalOnMissingBean(BattleSessionWaitActionHandler::class)
    fun battleSessionWaitActionHandler(): BattleSessionWaitActionHandler = BattleSessionWaitActionHandler()

    @Bean
    @ConditionalOnMissingBean(BattleSessionActionHandlerRegistry::class)
    fun battleSessionActionHandlerRegistry(
        handlers: List<BattleSessionActionHandler>,
    ): BattleSessionActionHandlerRegistry = InMemoryBattleSessionActionHandlerRegistry(handlers)

    @Bean
    @ConditionalOnMissingBean(BattleSessionTurnValidationStep::class)
    fun battleSessionTurnValidationStep(): BattleSessionTurnValidationStep = BattleSessionTurnValidationStep()

    @Bean
    @ConditionalOnMissingBean(BattleSessionBeforeTurnStep::class)
    fun battleSessionBeforeTurnStep(): BattleSessionBeforeTurnStep = BattleSessionBeforeTurnStep()

    @Bean
    @ConditionalOnMissingBean(BattleSessionQueuedActionExecutionStep::class)
    fun battleSessionQueuedActionExecutionStep(): BattleSessionQueuedActionExecutionStep = BattleSessionQueuedActionExecutionStep()

    @Bean
    @ConditionalOnMissingBean(BattleSessionTurnAdvanceStep::class)
    fun battleSessionTurnAdvanceStep(): BattleSessionTurnAdvanceStep = BattleSessionTurnAdvanceStep()

    @Bean
    @ConditionalOnMissingBean(BattleSessionTurnPipeline::class)
    fun battleSessionTurnPipeline(
        steps: List<BattleSessionTurnStep>,
    ): BattleSessionTurnPipeline = DefaultBattleSessionTurnPipeline(steps)

    @Bean
    @ConditionalOnMissingBean
    fun battleSessionFactory(
        effectDefinitionRepository: EffectDefinitionRepository,
        battleFlowEngine: BattleFlowEngine,
        battleFlowPhaseProcessor: BattleFlowPhaseProcessor,
        battleMutationInterceptorChain: BattleMutationInterceptorChain,
        captureActionResolver: CaptureActionResolver,
        mutationApplier: MutationApplier,
        replacementStrategy: ReplacementStrategy,
        battleSessionActionExecutionSupport: BattleSessionActionExecutionSupport,
        battleSessionChoiceHandlerRegistry: BattleSessionChoiceHandlerRegistry,
        battleSessionActionHandlerRegistry: BattleSessionActionHandlerRegistry,
        battleSessionTurnPipeline: BattleSessionTurnPipeline,
        battleSessionTurnReadySpecification: BattleSessionTurnReadySpecification,
        battleSessionUnitChoiceSpecification: BattleSessionUnitChoiceSpecification,
        battleSessionRunChoiceSpecification: BattleSessionRunChoiceSpecification,
        battleSessionTargetChoiceSpecification: BattleSessionTargetChoiceSpecification,
        battleSessionCaptureChoiceSpecification: BattleSessionCaptureChoiceSpecification,
        battleSessionMoveChoiceSpecification: BattleSessionMoveChoiceSpecification,
        battleSessionItemChoiceSpecification: BattleSessionItemChoiceSpecification,
        battleSessionTargetQueryService: BattleSessionTargetQueryService,
        battleSessionActionSortingStrategy: BattleSessionActionSortingStrategy,
        battleSessionEventPublisher: BattleSessionEventPublisher,
        battleSessionCommandFactory: BattleSessionCommandFactory,
    ): BattleSessionFactory =
        DefaultBattleSessionFactory(
            effectRepository = effectDefinitionRepository,
            battleFlowEngine = battleFlowEngine,
            battleFlowPhaseProcessor = battleFlowPhaseProcessor,
            battleMutationInterceptorChain = battleMutationInterceptorChain,
            captureActionResolver = captureActionResolver,
            mutationApplier = mutationApplier,
            replacementStrategy = replacementStrategy,
            actionExecutionSupport = battleSessionActionExecutionSupport,
            choiceHandlerRegistry = battleSessionChoiceHandlerRegistry,
            actionHandlerRegistry = battleSessionActionHandlerRegistry,
            turnPipeline = battleSessionTurnPipeline,
            turnReadySpecification = battleSessionTurnReadySpecification,
            unitChoiceSpecification = battleSessionUnitChoiceSpecification,
            runChoiceSpecification = battleSessionRunChoiceSpecification,
            targetChoiceSpecification = battleSessionTargetChoiceSpecification,
            captureChoiceSpecification = battleSessionCaptureChoiceSpecification,
            moveChoiceSpecification = battleSessionMoveChoiceSpecification,
            itemChoiceSpecification = battleSessionItemChoiceSpecification,
            targetQueryService = battleSessionTargetQueryService,
            actionSortingStrategy = battleSessionActionSortingStrategy,
            eventPublisher = battleSessionEventPublisher,
            commandFactory = battleSessionCommandFactory,
        )

    @Bean
    @ConditionalOnMissingBean(BattleSessionStore::class)
    fun inMemoryBattleSessionStore(): BattleSessionStore = InMemoryBattleSessionStore()

    @Bean
    @ConditionalOnMissingBean
    fun battleSessionGateway(
        sessionFactory: BattleSessionFactory,
        battleSessionStore: BattleSessionStore,
    ): BattleSessionGateway = InMemoryBattleSessionGateway(sessionFactory, battleSessionStore)

    @Bean
    @ConditionalOnMissingBean
    fun battleChoiceResolver(
        effectDefinitionRepository: EffectDefinitionRepository,
        battleSessionTargetQueryService: BattleSessionTargetQueryService,
    ): BattleChoiceResolver =
        BattleChoiceResolver(
            effectDefinitionRepository = effectDefinitionRepository,
            targetQueryService = battleSessionTargetQueryService,
        )

    @Bean
    @ConditionalOnMissingBean(StandardBattleSettlementPlanner::class)
    fun standardBattleSettlementPlanner(): StandardBattleSettlementPlanner = StandardBattleSettlementPlanner()

    @Bean
    @ConditionalOnMissingBean(WildBattleSettlementPlanner::class)
    fun wildBattleSettlementPlanner(): WildBattleSettlementPlanner = WildBattleSettlementPlanner()

    @Bean
    @ConditionalOnMissingBean(BattleEngineService::class)
    fun battleEngineService(
        battleSessionGateway: BattleSessionGateway,
        battleChoiceResolver: BattleChoiceResolver,
        battleAiChoiceProviders: List<BattleAiChoiceProvider>,
        battleSettlementPlanners: List<BattleSettlementPlanner>,
    ): BattleEngineService =
        DefaultBattleEngineService(
            battleSessionGateway = battleSessionGateway,
            battleChoiceResolver = battleChoiceResolver,
            battleAiChoiceProviders = battleAiChoiceProviders,
            battleSettlementPlanners = battleSettlementPlanners,
        )
}