package openai

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"iop/packages/go/config"
)

const hotPathInitialAdmissionMetadata = "iop_hot_path_initial_admission"

func isInitialHotPathAdmission(metadata map[string]string) bool {
	return metadata != nil && metadata[hotPathInitialAdmissionMetadata] == "true"
}

func (s *Server) hotPathSelectorProviderInstruction(metadata map[string]string) (string, error) {
	if s == nil || s.artifactFrontiers == nil || metadata == nil {
		return "", nil
	}
	requestID := strings.TrimSpace(metadata["iop_logical_request_id"])
	state := s.artifactFrontiers.selectorInstructionState(requestID, s.edgeIDValue())
	if state == selectorInstructionNone {
		return "", nil
	}
	return buildHotPathSelectorProviderInstruction(requestID, state)
}

func (s *Server) joinPresetChatIngress(r *http.Request, dispatch routeDispatch, rawBody []byte, runMeta map[string]string) (presetIngressResult, error) {
	delete(runMeta, hotPathInitialAdmissionMetadata)
	s.sweepLogicalRequestTTL()
	requestContext := context.Background()
	if r != nil {
		requestContext = r.Context()
	}
	ownerEdgeID := s.edgeIDValue()
	principalRef := runMeta[principalMetaRef]
	if principalRef == "" {
		principalRef = dispatch.PrincipalRef
	}
	if principalRef == "" {
		principalRef = "anonymous"
	}
	presetGen := dispatch.PresetID
	if presetGen == "" {
		presetGen = dispatch.Preset.ID
	}
	if presetGen == "" {
		presetGen = dispatch.ExternalModelID
	}
	if presetGen == "" {
		presetGen = "gen-1"
	}

	if hasChatContinuationStructure(rawBody) {
		contLineage, err := newChatContinuationLineage(rawBody)
		if err != nil {
			return presetIngressResult{}, fmt.Errorf("invalid preset continuation payload: %w", err)
		}
		if s.artifactFrontiers != nil {
			snap, disposition, matched, err := s.artifactFrontiers.consumeChat(
				ownerEdgeID, principalRef, rawBody, contLineage, s.requestCoordinator, s.lightFlows,
			)
			if matched {
				if err != nil {
					return presetIngressResult{}, fmt.Errorf("artifact continuation rejected: %w", err)
				}
				if disposition.PrimaryError != nil {
					if err := s.lightFlows.updateArtifactLineage(snap.ID, ownerEdgeID, contLineage.Committed, false, nil); err != nil {
						return presetIngressResult{}, err
					}
					cleanup, err := s.lightFlows.beginPrimaryErrorCleanup(requestContext, snap.ID, ownerEdgeID, *disposition.PrimaryError, nil, s.requestCoordinator)
					if err != nil {
						if contextErr := requestContext.Err(); contextErr != nil {
							return presetIngressResult{}, contextErr
						}
						runMeta["iop_logical_request_id"] = snap.ID
						return presetIngressResult{Terminal: s.retainHotPathPrimaryErrorForTTL(snap.ID, *disposition.PrimaryError)}, nil
					}
					s.observeHotPathCleanupTransition(requestContext, snap.ID, dispatch.Preset.ID)
					return presetIngressResult{Cleanup: &hotPathCleanupTurn{RequestID: snap.ID, Output: cleanup}}, nil
				}
				if err := s.applyArtifactDisposition(snap, disposition, runMeta); err != nil {
					return presetIngressResult{}, err
				}
				if err := s.lightFlows.updateArtifactLineage(snap.ID, ownerEdgeID, contLineage.Committed, disposition.Kind == artifactDispositionLocalEligible, disposition.PlanItemIDs); err != nil {
					return presetIngressResult{}, err
				}
				return presetIngressResult{Artifact: disposition}, nil
			}
		}
		if s.lightFlows != nil {
			snap, disposition, matched, err := s.lightFlows.consumeChat(ownerEdgeID, principalRef, rawBody, contLineage, s.requestCoordinator)
			if matched {
				if err != nil {
					return presetIngressResult{}, fmt.Errorf("light continuation rejected: %w", err)
				}
				if disposition.Terminal != nil {
					s.artifactFrontiers.remove(disposition.RequestID, ownerEdgeID)
					runMeta["iop_logical_request_id"] = disposition.RequestID
					return presetIngressResult{Terminal: disposition.Terminal}, nil
				}
				if err := s.applyLightDisposition(snap, disposition, runMeta, dispatch.Preset.ID); err != nil {
					return presetIngressResult{}, err
				}
				return presetIngressResult{Light: disposition}, nil
			}
		}
		snap, err := s.requestCoordinator.consumeContinuationByLineage(ownerEdgeID, principalRef, contLineage)
		if err != nil {
			return presetIngressResult{}, fmt.Errorf("preset continuation rejected: %w", err)
		}
		stageID, err := s.requestCoordinator.newStageID()
		if err != nil {
			return presetIngressResult{}, err
		}
		callID, err := s.requestCoordinator.newCallID()
		if err != nil {
			return presetIngressResult{}, err
		}
		if _, err := s.requestCoordinator.activateStage(snap.ID, ownerEdgeID, stageID); err != nil {
			return presetIngressResult{}, err
		}
		runMeta["iop_logical_request_id"] = snap.ID
		runMeta["iop_call_id"] = callID
		runMeta["iop_stage_id"] = stageID
		return presetIngressResult{}, nil
	}

	initLineage, err := newChatRequestLineage(rawBody)
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("invalid preset request payload: %w", err)
	}
	binding, pinArtifact, err := s.compilePresetArtifactBinding(dispatch, "openai", rawBody)
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("preset workspace admission failed: %w", err)
	}
	snap, err := s.requestCoordinator.create(logicalRequestAdmission{
		OwnerEdgeID:      ownerEdgeID,
		PrincipalRef:     principalRef,
		Lineage:          initLineage,
		PresetGeneration: presetGen,
	})
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("preset begin admission failed: %w", err)
	}
	stageID, err := s.requestCoordinator.newStageID()
	if err != nil {
		return presetIngressResult{}, err
	}
	callID, err := s.requestCoordinator.newCallID()
	if err != nil {
		return presetIngressResult{}, err
	}
	if _, err := s.requestCoordinator.activateStage(snap.ID, ownerEdgeID, stageID); err != nil {
		return presetIngressResult{}, err
	}
	if pinArtifact {
		if err := s.artifactFrontiers.pin(snap.ID, ownerEdgeID, principalRef, "openai", stageID, initLineage, binding); err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("pin preset workspace binding: %w", err)
		}
		task, tools, err := hotPathIngressSeed("openai", rawBody)
		if err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("capture light input: %w", err)
		}
		if err := s.lightFlows.pin(snap.ID, ownerEdgeID, principalRef, "openai", stageID, initLineage, task, tools, binding, dispatch.Preset, dispatch); err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("pin light flow: %w", err)
		}
	}
	runMeta["iop_logical_request_id"] = snap.ID
	runMeta["iop_call_id"] = callID
	runMeta["iop_stage_id"] = stageID
	runMeta[hotPathInitialAdmissionMetadata] = "true"
	return presetIngressResult{}, nil
}

func (s *Server) joinPresetAnthropicIngress(r *http.Request, dispatch routeDispatch, rawBody []byte, metadata map[string]string) (presetIngressResult, error) {
	delete(metadata, hotPathInitialAdmissionMetadata)
	s.sweepLogicalRequestTTL()
	requestContext := context.Background()
	if r != nil {
		requestContext = r.Context()
	}
	ownerEdgeID := s.edgeIDValue()
	principalRef := metadata[principalMetaRef]
	if principalRef == "" {
		principalRef = dispatch.PrincipalRef
	}
	if principalRef == "" {
		principalRef = "anonymous"
	}
	presetGen := dispatch.PresetID
	if presetGen == "" {
		presetGen = dispatch.Preset.ID
	}
	if presetGen == "" {
		presetGen = dispatch.ExternalModelID
	}
	if presetGen == "" {
		presetGen = "gen-1"
	}

	if hasAnthropicContinuationStructure(rawBody) {
		contLineage, err := newAnthropicContinuationLineage(rawBody)
		if err != nil {
			return presetIngressResult{}, fmt.Errorf("invalid preset continuation payload: %w", err)
		}
		if s.artifactFrontiers != nil {
			snap, disposition, matched, err := s.artifactFrontiers.consumeAnthropic(
				ownerEdgeID, principalRef, rawBody, contLineage, s.requestCoordinator, s.lightFlows,
			)
			if matched {
				if err != nil {
					return presetIngressResult{}, fmt.Errorf("artifact continuation rejected: %w", err)
				}
				if disposition.PrimaryError != nil {
					if err := s.lightFlows.updateArtifactLineage(snap.ID, ownerEdgeID, contLineage.Committed, false, nil); err != nil {
						return presetIngressResult{}, err
					}
					cleanup, err := s.lightFlows.beginPrimaryErrorCleanup(requestContext, snap.ID, ownerEdgeID, *disposition.PrimaryError, nil, s.requestCoordinator)
					if err != nil {
						if contextErr := requestContext.Err(); contextErr != nil {
							return presetIngressResult{}, contextErr
						}
						metadata["iop_logical_request_id"] = snap.ID
						return presetIngressResult{Terminal: s.retainHotPathPrimaryErrorForTTL(snap.ID, *disposition.PrimaryError)}, nil
					}
					s.observeHotPathCleanupTransition(requestContext, snap.ID, dispatch.Preset.ID)
					return presetIngressResult{Cleanup: &hotPathCleanupTurn{RequestID: snap.ID, Output: cleanup}}, nil
				}
				if err := s.applyArtifactDisposition(snap, disposition, metadata); err != nil {
					return presetIngressResult{}, err
				}
				if err := s.lightFlows.updateArtifactLineage(snap.ID, ownerEdgeID, contLineage.Committed, disposition.Kind == artifactDispositionLocalEligible, disposition.PlanItemIDs); err != nil {
					return presetIngressResult{}, err
				}
				return presetIngressResult{Artifact: disposition}, nil
			}
		}
		if s.lightFlows != nil {
			snap, disposition, matched, err := s.lightFlows.consumeAnthropic(ownerEdgeID, principalRef, rawBody, contLineage, s.requestCoordinator)
			if matched {
				if err != nil {
					return presetIngressResult{}, fmt.Errorf("light continuation rejected: %w", err)
				}
				if disposition.Terminal != nil {
					s.artifactFrontiers.remove(disposition.RequestID, ownerEdgeID)
					metadata["iop_logical_request_id"] = disposition.RequestID
					return presetIngressResult{Terminal: disposition.Terminal}, nil
				}
				if err := s.applyLightDisposition(snap, disposition, metadata, dispatch.Preset.ID); err != nil {
					return presetIngressResult{}, err
				}
				return presetIngressResult{Light: disposition}, nil
			}
		}
		snap, err := s.requestCoordinator.consumeContinuationByLineage(ownerEdgeID, principalRef, contLineage)
		if err != nil {
			return presetIngressResult{}, fmt.Errorf("preset continuation rejected: %w", err)
		}
		stageID, err := s.requestCoordinator.newStageID()
		if err != nil {
			return presetIngressResult{}, err
		}
		callID, err := s.requestCoordinator.newCallID()
		if err != nil {
			return presetIngressResult{}, err
		}
		if _, err := s.requestCoordinator.activateStage(snap.ID, ownerEdgeID, stageID); err != nil {
			return presetIngressResult{}, err
		}
		metadata["iop_logical_request_id"] = snap.ID
		metadata["iop_call_id"] = callID
		metadata["iop_stage_id"] = stageID
		return presetIngressResult{}, nil
	}

	initLineage, err := newAnthropicRequestLineage(rawBody)
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("invalid preset request payload: %w", err)
	}
	binding, pinArtifact, err := s.compilePresetArtifactBinding(dispatch, "anthropic", rawBody)
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("preset workspace admission failed: %w", err)
	}
	snap, err := s.requestCoordinator.create(logicalRequestAdmission{
		OwnerEdgeID:      ownerEdgeID,
		PrincipalRef:     principalRef,
		Lineage:          initLineage,
		PresetGeneration: presetGen,
	})
	if err != nil {
		return presetIngressResult{}, fmt.Errorf("preset begin admission failed: %w", err)
	}
	stageID, err := s.requestCoordinator.newStageID()
	if err != nil {
		return presetIngressResult{}, err
	}
	callID, err := s.requestCoordinator.newCallID()
	if err != nil {
		return presetIngressResult{}, err
	}
	if _, err := s.requestCoordinator.activateStage(snap.ID, ownerEdgeID, stageID); err != nil {
		return presetIngressResult{}, err
	}
	if pinArtifact {
		if err := s.artifactFrontiers.pin(snap.ID, ownerEdgeID, principalRef, "anthropic", stageID, initLineage, binding); err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("pin preset workspace binding: %w", err)
		}
		task, tools, err := hotPathIngressSeed("anthropic", rawBody)
		if err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("capture light input: %w", err)
		}
		if err := s.lightFlows.pin(snap.ID, ownerEdgeID, principalRef, "anthropic", stageID, initLineage, task, tools, binding, dispatch.Preset, dispatch); err != nil {
			s.terminalPresetRequest(snap.ID, ownerEdgeID)
			return presetIngressResult{}, fmt.Errorf("pin light flow: %w", err)
		}
	}
	metadata["iop_logical_request_id"] = snap.ID
	metadata["iop_call_id"] = callID
	metadata["iop_stage_id"] = stageID
	metadata[hotPathInitialAdmissionMetadata] = "true"
	return presetIngressResult{}, nil
}

func (s *Server) applyLightDisposition(snap logicalRequestSnapshot, disposition hotPathLightDisposition, metadata map[string]string, presetID string) error {
	if metadata == nil || disposition.RequestID == "" || disposition.StageID == "" {
		return fmt.Errorf("light continuation metadata is unavailable")
	}
	callID, err := s.requestCoordinator.newCallID()
	if err != nil {
		return err
	}
	metadata["iop_logical_request_id"] = disposition.RequestID
	metadata["iop_call_id"] = callID
	metadata["iop_stage_id"] = disposition.StageID
	if disposition.TransitionFrom == hotPathPhaseLocalActive && disposition.Phase == hotPathPhaseReviewActive {
		s.observeHotPathLightTransition(context.Background(), hotPathStageKindReview, hotPathAttemptFirst,
			disposition.RequestID, disposition.StageID, presetID)
	}
	if disposition.TransitionFrom == hotPathPhaseReviewActive && disposition.Phase == hotPathPhaseReviewRepair {
		s.observeHotPathLightTransition(context.Background(), hotPathStageKindReview, hotPathAttemptRetry,
			disposition.RequestID, disposition.StageID, presetID)
	}
	_ = snap
	return nil
}

func hotPathIngressSeed(protocol string, rawBody []byte) (string, any, error) {
	tools, err := decodeArtifactTools(protocol, rawBody)
	if err != nil {
		return "", nil, err
	}
	switch protocol {
	case "openai":
		var req chatCompletionRequest
		if err := decodeChatCompletionRequestLenient(json.NewDecoder(strings.NewReader(string(rawBody))), &req); err != nil {
			return "", nil, err
		}
		return promptFromMessages(req.Messages), tools, nil
	case "anthropic":
		req, err := decodeAnthropicMessageRequest(rawBody, true)
		if err != nil {
			return "", nil, err
		}
		var parts []string
		system, err := decodeAnthropicSystem(req.System)
		if err != nil {
			return "", nil, err
		}
		for _, block := range system {
			if strings.TrimSpace(block.Text) != "" {
				parts = append(parts, "system: "+strings.TrimSpace(block.Text))
			}
		}
		for _, message := range req.Messages {
			blocks, err := decodeAnthropicContent(message.Content)
			if err != nil {
				return "", nil, err
			}
			for _, block := range blocks {
				if block.Type == "text" && strings.TrimSpace(block.Text) != "" {
					parts = append(parts, message.Role+": "+strings.TrimSpace(block.Text))
				}
			}
		}
		return strings.Join(parts, "\n"), tools, nil
	default:
		return "", nil, fmt.Errorf("unsupported hot path protocol %q", protocol)
	}
}

func (s *Server) compilePresetArtifactBinding(dispatch routeDispatch, protocol string, rawBody []byte) (*workspaceBinding, bool, error) {
	preset := dispatch.Preset
	if preset.ID == "" {
		if found, ok := s.ExecutionPreset(dispatch.PresetID); ok {
			preset = found
		}
	}
	if !presetAdmitsCallerWorkspaceTools(preset, dispatch) {
		return nil, false, nil
	}
	tools, err := decodeArtifactTools(protocol, rawBody)
	if err != nil {
		return nil, false, err
	}
	binding, err := compileWorkspaceBinding(preset.WorkspaceTools, tools)
	if err != nil {
		return nil, false, err
	}
	return binding, true, nil
}

// presetAdmitsCallerWorkspaceTools is the ownership discriminator for the two
// intentionally separate hybrid paths. An unmarked light preset may compile
// only caller-admitted tools; a marked single-request preset always retains its
// operator-owned workspace capability and never enters caller continuation.
func presetAdmitsCallerWorkspaceTools(preset config.ExecutionPreset, dispatch routeDispatch) bool {
	if preset.SingleRequest != nil || dispatch.SingleRequest != nil {
		return false
	}
	return isModeAllowed(preset, modeLight)
}

func hasChatContinuationStructure(rawBody []byte) bool {
	var env struct {
		Messages []struct {
			Role string `json:"role"`
		} `json:"messages"`
	}
	if err := json.Unmarshal(rawBody, &env); err != nil || len(env.Messages) == 0 {
		return false
	}
	lastRole := env.Messages[len(env.Messages)-1].Role
	return lastRole == "tool"
}

func hasAnthropicContinuationStructure(rawBody []byte) bool {
	var env struct {
		Messages []struct {
			Role    string          `json:"role"`
			Content json.RawMessage `json:"content"`
		} `json:"messages"`
	}
	if err := json.Unmarshal(rawBody, &env); err != nil || len(env.Messages) == 0 {
		return false
	}
	last := env.Messages[len(env.Messages)-1]
	if last.Role != "user" || len(last.Content) == 0 {
		return false
	}
	var blocks []struct {
		Type string `json:"type"`
	}
	if err := json.Unmarshal(last.Content, &blocks); err != nil || len(blocks) == 0 {
		return false
	}
	for _, b := range blocks {
		if b.Type == "tool_result" {
			return true
		}
	}
	return false
}
