package openai

import (
	"context"
	"fmt"
)

func (s *Server) advanceHotPathReview(
	ctx context.Context,
	requestID string,
	phase hotPathLightPhase,
	output normalizedStageOutput,
	visible normalizedStageOutput,
	outer *hotPathOuterTurn,
	protocol string,
) (normalizedStageOutput, bool, error) {
	kind, cleanup, err := classifyHotPathReviewOutput(requestID, phase, output)
	if err != nil {
		return normalizedStageOutput{}, false, err
	}
	if cleanup {
		terminalOutput := output.StageResponseOverlay(visible)
		if outer != nil {
			terminalOutput = hotPathCompatibilityOutput(outer, terminalOutput, protocol)
		}
		intent := hotPathTerminalIntent{Output: terminalOutput}
		mapped, err := s.lightFlows.beginCleanupWithOuter(ctx, requestID, s.edgeIDValue(), intent, outer, s.requestCoordinator)
		if err != nil {
			return normalizedStageOutput{}, false, err
		}
		return mapped, true, nil
	}
	mapped, err := s.lightFlows.issueTools(ctx, requestID, s.edgeIDValue(), output, visible, kind, outer, s.requestCoordinator)
	if err != nil {
		return normalizedStageOutput{}, false, err
	}
	return mapped, true, nil
}

func classifyHotPathReviewOutput(requestID string, phase hotPathLightPhase, output normalizedStageOutput) (hotPathPendingKind, bool, error) {
	paths := newReservedPaths(requestID)
	switch phase {
	case hotPathPhaseReviewActive:
		if len(output.ToolCalls) == 0 {
			return "", false, fmt.Errorf("review stage completed before writing the issued review artifact")
		}
		writeCount := 0
		reservedCount := 0
		for _, call := range output.ToolCalls {
			observed := reservedPathsFromToolCall(call)
			if len(observed) == 0 {
				continue
			}
			reservedCount++
			if len(observed) == 1 && cleanRelativePath(observed[0]) == cleanRelativePath(paths.ReviewPath) {
				writeCount++
			}
		}
		if writeCount == 0 && reservedCount == 0 {
			return hotPathPendingReviewInspection, false, nil
		}
		if writeCount == 1 && reservedCount == 1 && len(output.ToolCalls) == 1 {
			return hotPathPendingReviewWrite, false, nil
		}
		return "", false, fmt.Errorf("review write must be one exact review-path tool call")

	case hotPathPhaseReviewAwaitRead:
		if len(output.ToolCalls) != 1 {
			return "", false, fmt.Errorf("review write result must be followed by one exact review read")
		}
		observed := reservedPathsFromToolCall(output.ToolCalls[0])
		if len(observed) != 1 || cleanRelativePath(observed[0]) != cleanRelativePath(paths.ReviewPath) {
			return "", false, fmt.Errorf("review write result must be followed by the issued review read")
		}
		return hotPathPendingReviewRead, false, nil

	case hotPathPhaseReviewResolution:
		if len(output.ToolCalls) == 0 {
			return "", true, nil
		}
		for _, call := range output.ToolCalls {
			if len(reservedPathsFromToolCall(call)) > 0 {
				return "", false, fmt.Errorf("review resolution cannot start another reserved review cycle")
			}
		}
		return hotPathPendingReviewRepair, false, nil

	case hotPathPhaseReviewRepair:
		if len(output.ToolCalls) == 0 {
			return "", true, nil
		}
		for _, call := range output.ToolCalls {
			if len(reservedPathsFromToolCall(call)) > 0 {
				return "", false, fmt.Errorf("repair cannot start a second review cycle")
			}
		}
		return hotPathPendingReviewRepair, false, nil

	default:
		return "", false, fmt.Errorf("phase %q is not a review phase", phase)
	}
}
