package api

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestDocsEndpointSchemeDetection(t *testing.T) {
	// Create a simple app with docs enabled
	app := New("test-api")
	spec := NewOpenAPISpec("Test API", "1.0.0")
	app.EnableDocs(spec)

	tests := []struct {
		name            string
		xForwardedProto string
		expectedScheme  string
	}{
		{
			name:            "no header defaults to http",
			xForwardedProto: "",
			expectedScheme:  "http",
		},
		{
			name:            "X-Forwarded-Proto https",
			xForwardedProto: "https",
			expectedScheme:  "https",
		},
		{
			name:            "X-Forwarded-Proto http",
			xForwardedProto: "http",
			expectedScheme:  "http",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req := httptest.NewRequest(http.MethodGet, "/docs", nil)
			if tt.xForwardedProto != "" {
				req.Header.Set("X-Forwarded-Proto", tt.xForwardedProto)
			}
			rec := httptest.NewRecorder()

			app.ServeHTTP(rec, req)

			if rec.Code != http.StatusOK {
				t.Fatalf("expected status 200, got %d", rec.Code)
			}

			body := rec.Body.String()
			expectedURL := tt.expectedScheme + "://"
			if !strings.Contains(body, expectedURL) {
				t.Errorf("expected body to contain %q scheme URL", expectedURL)
			}
		})
	}
}

func TestOpenAPISpec(t *testing.T) {
	spec := NewOpenAPISpec("Test API", "1.0.0").
		WithDescription("Test description").
		WithServer("https://api.example.com", "Production").
		WithTag("test", "Test operations")

	// Add a path
	spec.AddPath("/test", "get", Op("Get test", "Gets a test", "test"))

	// Generate JSON
	jsonBytes, err := spec.JSON()
	if err != nil {
		t.Fatalf("failed to generate JSON: %v", err)
	}

	json := string(jsonBytes)

	// Verify content
	if !strings.Contains(json, `"title": "Test API"`) {
		t.Error("expected title in JSON")
	}
	if !strings.Contains(json, `"version": "1.0.0"`) {
		t.Error("expected version in JSON")
	}
	if !strings.Contains(json, `"description": "Test description"`) {
		t.Error("expected description in JSON")
	}
	if !strings.Contains(json, `"url": "https://api.example.com"`) {
		t.Error("expected server URL in JSON")
	}
	if !strings.Contains(json, `"/test"`) {
		t.Error("expected path in JSON")
	}
}

func TestOpenAPIJSONEndpoint(t *testing.T) {
	app := New("test-api")
	spec := NewOpenAPISpec("Test API", "1.0.0")
	app.EnableDocs(spec)

	req := httptest.NewRequest(http.MethodGet, "/openapi.json", nil)
	rec := httptest.NewRecorder()

	app.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", rec.Code)
	}

	contentType := rec.Header().Get("Content-Type")
	if contentType != "application/json" {
		t.Errorf("expected Content-Type application/json, got %s", contentType)
	}

	// Check CORS header
	cors := rec.Header().Get("Access-Control-Allow-Origin")
	if cors != "*" {
		t.Errorf("expected CORS header *, got %s", cors)
	}
}
