GameBattleRequestAssembler.kt

package io.github.lishangbu.avalon.game.battle.api

import io.github.lishangbu.avalon.game.battle.engine.application.SubmitCaptureChoiceCommand
import io.github.lishangbu.avalon.game.battle.engine.application.SubmitItemChoiceCommand
import io.github.lishangbu.avalon.game.battle.engine.application.SubmitMoveChoiceCommand
import io.github.lishangbu.avalon.game.battle.engine.application.SubmitReplacementChoiceCommand
import io.github.lishangbu.avalon.game.battle.engine.application.SubmitRunChoiceCommand
import io.github.lishangbu.avalon.game.battle.engine.application.SubmitSwitchChoiceCommand
import io.github.lishangbu.avalon.game.battle.init.CreateImportedBattleSessionRequest
import io.github.lishangbu.avalon.game.battle.init.ImportedBattleSideRequest
import io.github.lishangbu.avalon.game.service.unit.BattleMoveImportRequest
import io.github.lishangbu.avalon.game.service.unit.BattleUnitImportMetadata
import io.github.lishangbu.avalon.game.service.unit.BattleUnitImportRequest
import org.springframework.stereotype.Component

/**
 * battle 接口层请求组装器。
 *
 * 设计意图:
 * - 把 controller 接收到的前端 request view 映射为 battle 应用层使用的请求模型。
 * - 让 controller 不直接拼装 engine command 和初始化输入,保持接口层职责单一。
 */
@Component
class GameBattleRequestAssembler {
    /**
     * 把导入建局 API 请求映射为 battle 内部请求。
     */
    fun toCreateImportedSessionRequest(request: CreateImportedBattleSessionApiRequest): CreateImportedBattleSessionRequest =
        CreateImportedBattleSessionRequest(
            sessionId = request.sessionId,
            formatId = request.formatId,
            sides = request.sides.map(::toImportedBattleSideRequest),
            battleKind = request.battleKind,
            capturableSideId = request.capturableSideId,
            autoStart = request.autoStart,
        )

    /**
     * 把导入 side API 请求映射为 battle 内部请求。
     */
    private fun toImportedBattleSideRequest(request: GameBattleImportedSideApiRequest): ImportedBattleSideRequest =
        ImportedBattleSideRequest(
            sideId = request.sideId,
            units = request.units.map(::toBattleUnitImportRequest),
            activeUnitIds = request.activeUnitIds,
        )

    /**
     * 把导入单位 API 请求映射为 battle 内部请求。
     */
    private fun toBattleUnitImportRequest(request: GameBattleImportedUnitApiRequest): BattleUnitImportRequest =
        BattleUnitImportRequest(
            unitId = request.unitId,
            metadata =
                BattleUnitImportMetadata(
                    level = request.metadata.level,
                    creatureId = request.metadata.creatureId,
                    creatureInternalName = request.metadata.creatureInternalName,
                    natureId = request.metadata.natureId,
                    natureInternalName = request.metadata.natureInternalName,
                    captureContext = request.metadata.captureContext,
                    ivs = request.metadata.ivs,
                    evs = request.metadata.evs,
                ),
            abilityInternalName = request.abilityInternalName,
            itemId = request.itemId,
            moves = request.moves.map(::toBattleMoveImportRequest),
            currentHp = request.currentHp,
            statusState = request.statusState,
            volatileStates = request.volatileStates,
            conditionStates = request.conditionStates,
            boosts = request.boosts,
            forceSwitchRequested = request.forceSwitchRequested,
        )

    /**
     * 把导入招式 API 请求映射为 battle 内部请求。
     */
    private fun toBattleMoveImportRequest(request: GameBattleImportedMoveApiRequest): BattleMoveImportRequest =
        BattleMoveImportRequest(
            moveId = request.moveId,
            currentPp = request.currentPp,
        )

    /**
     * 把智能出招 API 请求映射为引擎应用命令。
     */
    fun toSubmitMoveChoiceCommand(request: SmartMoveChoiceRequest): SubmitMoveChoiceCommand =
        SubmitMoveChoiceCommand(
            attackerId = request.attackerId,
            moveId = request.moveId,
            targetId = request.targetId,
            priority = request.priority,
            speed = request.speed,
            accuracy = request.accuracy,
            evasion = request.evasion,
            basePower = request.basePower,
            damage = request.damage,
            accuracyRoll = request.accuracyRoll,
            chanceRoll = request.chanceRoll,
            criticalRoll = request.criticalRoll,
            damageRoll = request.damageRoll,
            criticalHit = request.criticalHit,
            attributes = request.attributes,
        )

    /**
     * 把智能用道具 API 请求映射为引擎应用命令。
     */
    fun toSubmitItemChoiceCommand(request: SmartItemChoiceRequest): SubmitItemChoiceCommand =
        SubmitItemChoiceCommand(
            actorUnitId = request.actorUnitId,
            itemId = request.itemId,
            targetId = request.targetId,
            priority = request.priority,
            speed = request.speed,
            chanceRoll = request.chanceRoll,
            attributes = request.attributes,
        )

    /**
     * 把智能捕捉 API 请求映射为引擎应用命令。
     */
    fun toSubmitCaptureChoiceCommand(request: SmartCaptureChoiceRequest): SubmitCaptureChoiceCommand =
        SubmitCaptureChoiceCommand(
            playerId = request.playerId,
            ballItemId = request.ballItemId,
            sourceUnitId = request.sourceUnitId,
            targetId = request.targetId,
            priority = request.priority,
            speed = request.speed,
        )

    /**
     * 把换人 API 请求映射为引擎应用命令。
     */
    fun toSubmitSwitchChoiceCommand(request: SubmitSwitchChoiceRequest): SubmitSwitchChoiceCommand =
        SubmitSwitchChoiceCommand(
            sideId = request.sideId,
            outgoingUnitId = request.outgoingUnitId,
            incomingUnitId = request.incomingUnitId,
            priority = request.priority,
            speed = request.speed,
        )

    /**
     * 把逃跑 API 请求映射为引擎应用命令。
     */
    fun toSubmitRunChoiceCommand(request: SubmitRunChoiceRequest): SubmitRunChoiceCommand =
        SubmitRunChoiceCommand(
            sideId = request.sideId,
            priority = request.priority,
            speed = request.speed,
        )

    /**
     * 把替补 API 请求映射为引擎应用命令。
     */
    fun toSubmitReplacementChoiceCommand(request: SubmitReplacementChoiceRequest): SubmitReplacementChoiceCommand =
        SubmitReplacementChoiceCommand(
            sideId = request.sideId,
            incomingUnitId = request.incomingUnitId,
        )
}