package access

import (
	"context"
	"fmt"
	"strings"
	"time"

	"sub2api-cn-relay-manager/internal/host/sub2api"
)

func (s *Service) verifyGatewayClosure(ctx context.Context, req ClosureRequest, plan closurePlan) (sub2api.GatewayAccessResult, error) {
	if plan.effectiveProbeAPIKey == "" {
		return sub2api.GatewayAccessResult{}, fmt.Errorf("access probe api key is required to verify gateway closure")
	}
	result, err := s.host.CheckGatewayAccess(ctx, sub2api.GatewayAccessCheckRequest{
		APIKey:        plan.effectiveProbeAPIKey,
		ExpectedModel: req.ExpectedModel,
	})
	if err != nil {
		return sub2api.GatewayAccessResult{}, fmt.Errorf("check gateway access: %w", err)
	}
	result.EffectiveProbeAPIKey = plan.effectiveProbeAPIKey
	result.EffectiveProbeKeySource = plan.effectiveProbeKeySource
	if result.OK && result.HasExpectedModel && strings.TrimSpace(req.ExpectedModel) != "" {
		completionReq := sub2api.GatewayCompletionCheckRequest{
			APIKey:    plan.effectiveProbeAPIKey,
			Model:     req.ExpectedModel,
			Prompt:    req.Prompt,
			MaxTokens: req.MaxTokens,
		}
		completion, err := s.checkGatewayCompletionWithRetry(ctx, completionReq)
		if err != nil {
			return sub2api.GatewayAccessResult{}, fmt.Errorf("check gateway completion: %w", err)
		}
		completion, err = s.maybeRepairOpenAIResponsesCapability(ctx, req, completionReq, completion)
		if err != nil {
			return sub2api.GatewayAccessResult{}, fmt.Errorf("re-check gateway completion after capability repair: %w", err)
		}
		result.CompletionOK = completion.OK
		result.CompletionStatus = completion.StatusCode
		result.CompletionType = completion.ContentType
		result.CompletionBody = completion.BodyPreview
	}
	return result, nil
}

func (s *Service) checkGatewayCompletionWithRetry(ctx context.Context, req sub2api.GatewayCompletionCheckRequest) (sub2api.GatewayCompletionResult, error) {
	var last sub2api.GatewayCompletionResult
	for attempt := 1; attempt <= gatewayCompletionRetryAttempts; attempt++ {
		completion, err := s.host.CheckGatewayCompletion(ctx, req)
		if err != nil {
			return sub2api.GatewayCompletionResult{}, err
		}
		last = completion
		if completion.OK || !isTransientGatewayCompletionFailure(completion) || attempt == gatewayCompletionRetryAttempts {
			return completion, nil
		}
		timer := time.NewTimer(gatewayCompletionRetryDelay)
		select {
		case <-ctx.Done():
			timer.Stop()
			return last, ctx.Err()
		case <-timer.C:
		}
	}
	return last, nil
}

func isTransientGatewayCompletionFailure(result sub2api.GatewayCompletionResult) bool {
	if result.OK {
		return false
	}
	if result.StatusCode != 0 && result.StatusCode != 429 && result.StatusCode != 502 && result.StatusCode != 503 && result.StatusCode != 504 {
		return false
	}
	body := strings.ToLower(strings.TrimSpace(result.BodyPreview))
	return strings.Contains(body, "service temporarily unavailable") ||
		strings.Contains(body, "no available accounts") ||
		strings.Contains(body, "temporar") ||
		strings.Contains(body, "try again")
}
