package com.correx.apps.server.approval

import com.correx.apps.server.protocol.ApprovalDecision
import com.correx.apps.server.protocol.ClientMessage
import com.correx.core.approvals.ApprovalOutcome
import com.correx.core.approvals.ApprovalStatus
import com.correx.core.approvals.Tier
import com.correx.core.approvals.UserSteering
import com.correx.core.approvals.model.ApprovalContext
import com.correx.core.approvals.model.ApprovalScopeIdentity
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.core.sessions.ApprovalMode
import kotlinx.datetime.Clock
import com.correx.core.approvals.model.ApprovalDecision as DomainApprovalDecision

/**
 * Translates a wire-level [ClientMessage.ApprovalResponse] into a domain [DomainApprovalDecision].
 *
 * Outcome is driven purely by [ClientMessage.ApprovalResponse.decision]:
 *   APPROVE -> APPROVED, REJECT -> REJECTED.
 *
 * A non-null [ClientMessage.ApprovalResponse.steeringNote] attaches a [UserSteering] regardless of
 * the approve/reject decision — the user may steer alongside either choice.
 */
internal fun ClientMessage.ApprovalResponse.toDomain(
    sessionId: SessionId,
    stageId: StageId?,
    tier: Tier,
): DomainApprovalDecision {
    val outcome = when (decision) {
        ApprovalDecision.APPROVE -> ApprovalOutcome.APPROVED
        ApprovalDecision.REJECT -> ApprovalOutcome.REJECTED
    }
    val identity = ApprovalScopeIdentity(sessionId = sessionId, stageId = stageId, projectId = null)
    val context = ApprovalContext(identity = identity, mode = ApprovalMode.PROMPT)
    val steering = steeringNote?.let {
        UserSteering(text = it, sessionId = sessionId, timestamp = Clock.System.now())
    }
    return DomainApprovalDecision(
        id = null,
        requestId = requestId,
        outcome = outcome,
        state = ApprovalStatus.COMPLETED,
        tier = tier,
        contextSnapshot = context,
        resolutionTimestamp = Clock.System.now(),
        reason = steeringNote,
        userSteering = steering,
    )
}
