package space.nstart.pcp_tgu_service.service

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.web.server.ResponseStatusException
import space.nstart.pcp_tgu_service.domain.PlanDecision
import space.nstart.pcp_tgu_service.dto.PlanDecisionMessage
import space.nstart.pcp_tgu_service.entity.PlanIssueAttemptStatus
import space.nstart.pcp_tgu_service.repository.PlanIssueAttemptRepository
import space.nstart.pcp_tgu_service.repository.PlannedPlanRepository
import space.nstart.pcp_tgu_service.repository.SpacecraftPlanningStateJpaRepository
import java.time.LocalDateTime
import java.util.UUID

/**
 * Test-only helper: генерирует decision event для текущей active attempt persisted plan.
 */
@ConditionalOnProperty(prefix = "tgu.test-controller", name = ["enabled"], havingValue = "true")
@Service
class TestPlanDecisionService(
    private val plannedPlanRepository: PlannedPlanRepository,
    private val planIssueAttemptRepository: PlanIssueAttemptRepository,
    private val spacecraftPlanningStateJpaRepository: SpacecraftPlanningStateJpaRepository,
    private val handlePlanDecisionUseCase: HandlePlanDecisionUseCase
) {
    /**
     * Создаёт synthetic decision event и проводит его через тот же use case, что Kafka consumer.
     */
    fun generateDecision(planId: UUID, decision: PlanDecision, reason: String?): PlanDecisionMessage {
        val plan = plannedPlanRepository.findById(planId).orElse(null)
            ?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Plan with planId=$planId was not found")
        val state = spacecraftPlanningStateJpaRepository.findById(plan.spacecraftId).orElse(null)
            ?: throw ResponseStatusException(
                HttpStatus.CONFLICT,
                "Planning state for spacecraftId=${plan.spacecraftId} was not found"
            )
        if (state.activePlanId != planId || state.activeAttemptId == null) {
            throw ResponseStatusException(
                HttpStatus.CONFLICT,
                "Plan $planId is not the active plan waiting for decision"
            )
        }

        val attempt = planIssueAttemptRepository.findById(state.activeAttemptId!!).orElse(null)
            ?: throw ResponseStatusException(
                HttpStatus.CONFLICT,
                "Active attempt ${state.activeAttemptId} for plan $planId was not found"
            )
        if (attempt.planId != planId) {
            throw ResponseStatusException(
                HttpStatus.CONFLICT,
                "Active attempt ${attempt.attemptId} does not belong to plan $planId"
            )
        }
        if (attempt.status !in ACTIVE_ATTEMPT_STATUSES) {
            throw ResponseStatusException(
                HttpStatus.CONFLICT,
                "Attempt ${attempt.attemptId} is already terminal with status=${attempt.status}"
            )
        }

        val message = PlanDecisionMessage(
            eventId = UUID.randomUUID(),
            spacecraftId = plan.spacecraftId,
            planId = plan.planId,
            attemptId = attempt.attemptId,
            decision = decision,
            decisionTime = LocalDateTime.now(),
            reason = reason?.takeIf { it.isNotBlank() } ?: DEFAULT_REASON
        )
        handlePlanDecisionUseCase.handle(message)
        return message
    }

    private companion object {
        val ACTIVE_ATTEMPT_STATUSES = setOf(PlanIssueAttemptStatus.STARTING, PlanIssueAttemptStatus.STARTED)
        const val DEFAULT_REASON = "TEST_CONTROLLER"
    }
}
