package openai_compat

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

	"iop/packages/go/config"
	runtime "iop/packages/go/execution"
)

// Capabilities probes the provider and returns the adapter's advertised
// capabilities including available targets and concurrency limits.
func (a *Adapter) Capabilities(ctx context.Context) (runtime.Capabilities, error) {
	probeCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
	defer cancel()
	targets, err := a.fetchTargets(probeCtx)
	status := runtime.ProviderStatusAvailable
	if err != nil {
		status = runtime.ProviderStatusUnavailable
	}
	return runtime.Capabilities{
		AdapterName:      Name,
		InstanceKey:      a.instanceName,
		Targets:          targets,
		MaxConcurrency:   effectiveCapacity(a.capacity, 8),
		MaxQueue:         a.maxQueue,
		QueueTimeoutMS:   a.queueTimeoutMS,
		RequestTimeoutMS: a.requestTimeoutMS,
		ProviderStatus:   runtime.NormalizeProviderStatus(status),
	}, nil
}

// ProbeProvider checks endpoint availability and target presence using the
// OpenAI-compatible /v1/models endpoint, returning only the public baseline
// status values.
func (a *Adapter) ProbeProvider(ctx context.Context, target string) (runtime.ProviderProbeResult, error) {
	probeCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
	defer cancel()

	targets, err := a.fetchTargets(probeCtx)

	result := runtime.ProviderProbeResult{
		AdapterName: Name,
		InstanceKey: a.instanceName,
		Target:      target,
	}
	if a.provider != "" {
		result.Metadata = map[string]string{"provider": a.provider}
	}

	if err != nil {
		result.Status = runtime.ProviderStatusUnknown
		result.Detail = err.Error()
		return result, err
	}

	result.Targets = targets

	if target == "" {
		result.Status = runtime.NormalizeProviderStatus(runtime.ProviderStatusAvailable)
		return result, nil
	}

	found := false
	for _, t := range targets {
		if t == target {
			found = true
			break
		}
	}

	if found {
		result.Status = runtime.NormalizeProviderStatus(runtime.ProviderStatusAvailable)
	} else {
		result.Status = runtime.NormalizeProviderStatus(runtime.ProviderStatusUnavailable)
		result.Detail = fmt.Sprintf("target model %q not found in provider models", target)
	}

	return result, nil
}

func (a *Adapter) fetchTargets(ctx context.Context) ([]string, error) {
	if a.endpoint == "" && a.profile == nil {
		return nil, fmt.Errorf("openai_compat adapter: endpoint is required")
	}
	req, err := a.prepareRequest(ctx, http.MethodGet, string(config.OperationModels), "/v1/models", nil, nil, false)
	if err != nil {
		return nil, err
	}
	resp, err := a.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("status code %d", resp.StatusCode)
	}
	var models modelsResponse
	if err := json.NewDecoder(resp.Body).Decode(&models); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	out := make([]string, 0, len(models.Data))
	for _, model := range models.Data {
		if model.ID != "" {
			out = append(out, model.ID)
		}
	}
	return out, nil
}

func effectiveCapacity(capacity, defaultVal int) int {
	if capacity <= 0 {
		return defaultVal
	}
	return capacity
}
