GameBattleController.kt

package io.github.lishangbu.avalon.game.controller

import io.github.lishangbu.avalon.game.battle.api.CreateImportedBattleSessionApiRequest
import io.github.lishangbu.avalon.game.battle.api.GameBattleRequestAssembler
import io.github.lishangbu.avalon.game.battle.api.GameBattleSessionView
import io.github.lishangbu.avalon.game.battle.api.GameBattleSettlementView
import io.github.lishangbu.avalon.game.battle.api.GameBattleTargetQueryView
import io.github.lishangbu.avalon.game.battle.api.GameBattleTurnResultView
import io.github.lishangbu.avalon.game.battle.api.GameBattleViewAssembler
import io.github.lishangbu.avalon.game.battle.api.SmartCaptureChoiceRequest
import io.github.lishangbu.avalon.game.battle.api.SmartItemChoiceRequest
import io.github.lishangbu.avalon.game.battle.api.SmartMoveChoiceRequest
import io.github.lishangbu.avalon.game.battle.api.SubmitReplacementChoiceRequest
import io.github.lishangbu.avalon.game.battle.api.SubmitRunChoiceRequest
import io.github.lishangbu.avalon.game.battle.api.SubmitSwitchChoiceRequest
import io.github.lishangbu.avalon.game.battle.engine.application.BattleEngineService
import io.github.lishangbu.avalon.game.battle.init.BattleInitializationService
import io.github.lishangbu.avalon.game.battle.settlement.BattleSettlementExecutor
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

/** 游戏对战业务控制器。 */
@RestController
@RequestMapping("/game/battle")
class GameBattleController(
    private val battleInitializationService: BattleInitializationService,
    private val battleEngineService: BattleEngineService,
    private val battleSettlementExecutor: BattleSettlementExecutor,
    private val gameBattleRequestAssembler: GameBattleRequestAssembler,
    private val gameBattleViewAssembler: GameBattleViewAssembler,
) {
    /** 使用真实数据直接创建并导入战斗会话。 */
    @PostMapping("/sessions/imported")
    fun createImportedSession(
        @RequestBody request: CreateImportedBattleSessionApiRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleInitializationService.createImportedSession(
                gameBattleRequestAssembler.toCreateImportedSessionRequest(request),
            ),
        )

    /** 启动已创建的战斗会话。 */
    @PostMapping("/sessions/{sessionId}/start")
    fun startSession(
        @PathVariable sessionId: String,
    ): GameBattleSessionView = gameBattleViewAssembler.toSessionView(battleEngineService.startSession(sessionId))

    /** 查询当前战斗会话。 */
    @GetMapping("/sessions/{sessionId}")
    fun querySession(
        @PathVariable sessionId: String,
    ): GameBattleSessionView = gameBattleViewAssembler.toSessionView(battleEngineService.querySession(sessionId))

    /** 查询当前 effect 在会话中的可选目标。 */
    @GetMapping("/sessions/{sessionId}/targets")
    fun queryTargets(
        @PathVariable sessionId: String,
        @RequestParam effectId: String,
        @RequestParam actorUnitId: String,
    ): GameBattleTargetQueryView =
        gameBattleViewAssembler.toTargetQueryView(
            battleEngineService.queryTargets(sessionId, effectId, actorUnitId),
        )

    /** 提交智能出招。 */
    @PostMapping("/sessions/{sessionId}/choices/move")
    fun submitMoveChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SmartMoveChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitMoveChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitMoveChoiceCommand(request),
            ),
        )

    /** 提交智能用道具。 */
    @PostMapping("/sessions/{sessionId}/choices/item")
    fun submitItemChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SmartItemChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitItemChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitItemChoiceCommand(request),
            ),
        )

    /** 提交捕捉动作。 */
    @PostMapping("/sessions/{sessionId}/choices/capture")
    fun submitCaptureChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SmartCaptureChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitCaptureChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitCaptureChoiceCommand(request),
            ),
        )

    /** 提交换人。 */
    @PostMapping("/sessions/{sessionId}/choices/switch")
    fun submitSwitchChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SubmitSwitchChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitSwitchChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitSwitchChoiceCommand(request),
            ),
        )

    /** 提交逃跑。 */
    @PostMapping("/sessions/{sessionId}/choices/run")
    fun submitRunChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SubmitRunChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitRunChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitRunChoiceCommand(request),
            ),
        )

    /** 提交替补上场。 */
    @PostMapping("/sessions/{sessionId}/replacement")
    fun submitReplacementChoice(
        @PathVariable sessionId: String,
        @RequestBody request: SubmitReplacementChoiceRequest,
    ): GameBattleSessionView =
        gameBattleViewAssembler.toSessionView(
            battleEngineService.submitReplacementChoice(
                sessionId,
                gameBattleRequestAssembler.toSubmitReplacementChoiceCommand(request),
            ),
        )

    /** 结算当前回合。 */
    @PostMapping("/sessions/{sessionId}/resolve-turn")
    fun resolveTurn(
        @PathVariable sessionId: String,
    ): GameBattleTurnResultView = gameBattleViewAssembler.toTurnResultView(battleEngineService.resolveTurn(sessionId))

    /** 对已结束 battle 执行统一结算。 */
    @PostMapping("/sessions/{sessionId}/settle")
    fun settleSession(
        @PathVariable sessionId: String,
    ): GameBattleSettlementView =
        gameBattleViewAssembler.toSettlementView(
            battleSettlementExecutor.execute(
                battleEngineService.buildSettlementPlan(sessionId),
            ),
        )
}