package openai

import (
	"context"
	"fmt"
	"strings"
)

func (s *Server) advanceHotPathReview(
	ctx context.Context,
	requestID string,
	phase hotPathLightPhase,
	output normalizedStageOutput,
	visible normalizedStageOutput,
	outer *hotPathOuterTurn,
	protocol string,
) (normalizedStageOutput, bool, error) {
	evidence, err := s.lightFlows.reviewEvidence(requestID, s.edgeIDValue())
	if err != nil {
		return normalizedStageOutput{}, false, err
	}
	kind, cleanup, err := classifyHotPathReviewOutput(requestID, phase, output, evidence)
	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, evidence hotPathReviewEvidence) (hotPathPendingKind, bool, error) {
	paths := newReservedPaths(requestID)
	switch phase {
	case hotPathPhaseReviewActive:
		if len(output.ToolCalls) == 0 {
			if !evidence.planRead || !evidence.reviewRead || !evidence.inspected {
				return "", false, fmt.Errorf("review completion requires both artifact reads and a successful ordinary result inspection")
			}
			if strings.TrimSpace(output.Content) == "" {
				return "", false, fmt.Errorf("review terminal output must be non-empty")
			}
			return "", true, nil
		}
		for _, call := range output.ToolCalls {
			observed := reservedPathsFromToolCall(call)
			for _, path := range observed {
				clean := cleanRelativePath(path)
				if clean != cleanRelativePath(paths.PlanPath) && clean != cleanRelativePath(paths.ReviewPath) {
					return "", false, fmt.Errorf("review inspection targets an unissued artifact")
				}
			}
		}
		if evidence.planRead && evidence.reviewRead && evidence.inspected {
			for _, call := range output.ToolCalls {
				if len(reservedPathsFromToolCall(call)) > 0 {
					return "", false, fmt.Errorf("review repair cannot restart artifact inspection")
				}
			}
			return hotPathPendingReviewRepair, false, nil
		}
		return hotPathPendingReviewInspection, false, nil

	case hotPathPhaseReviewRepair:
		if len(output.ToolCalls) == 0 {
			if !evidence.planRead || !evidence.reviewRead || !evidence.inspected {
				return "", false, fmt.Errorf("repair completion requires retained review evidence")
			}
			if strings.TrimSpace(output.Content) == "" {
				return "", false, fmt.Errorf("review terminal output must be non-empty")
			}
			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)
	}
}
