package clients

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)

func TestVolcesClientSupportsDeyunEnvelope(t *testing.T) {
	var submitted bool
	var polled bool
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Authorization") != "Bearer deyun-secret" {
			t.Fatalf("unexpected authorization header: %q", r.Header.Get("Authorization"))
		}
		switch r.Method + " " + r.URL.Path {
		case "POST /c39/api/v3/video/tasks":
			submitted = true
			_ = json.NewEncoder(w).Encode(map[string]any{
				"code":       0,
				"request_id": "deyun-submit-request",
				"data":       map[string]any{"id": "deyun-task-1"},
			})
		case "GET /c39/api/v3/video/tasks/deyun-task-1":
			polled = true
			_ = json.NewEncoder(w).Encode(map[string]any{
				"code":       0,
				"request_id": "deyun-poll-request",
				"data": map[string]any{
					"id":         "deyun-task-1",
					"status":     "succeeded",
					"created_at": 123,
					"content": map[string]any{
						"video_url": "https://example.com/deyun.mp4",
					},
				},
			})
		default:
			t.Fatalf("unexpected request %s %s", r.Method, r.URL.Path)
		}
	}))
	defer server.Close()

	response, err := (VolcesClient{HTTPClient: server.Client()}).Run(context.Background(), Request{
		Kind:      "videos.generations",
		ModelType: "video_generate",
		Model:     "deyun-seedance-2.0-canary",
		Body: map[string]any{
			"prompt":         "A red cube rotates on a white table",
			"resolution":     "480p",
			"ratio":          "16:9",
			"duration":       4,
			"generate_audio": false,
		},
		Candidate: store.RuntimeModelCandidate{
			BaseURL:           server.URL + "/c39/api/v3",
			ProviderModelName: "doubao-seedance-2-0",
			Credentials:       map[string]any{"apiKey": "deyun-secret"},
			PlatformConfig: map[string]any{
				"volcesPollIntervalMs":     100,
				"volcesPollTimeoutSeconds": 1,
				"volcesVideoTaskPath":      "/video/tasks",
			},
		},
	})
	if err != nil {
		t.Fatalf("run deyun-compatible video task: %v", err)
	}
	if !submitted || !polled {
		t.Fatalf("expected submit and poll, submitted=%v polled=%v", submitted, polled)
	}
	if response.RequestID != "deyun-poll-request" {
		t.Fatalf("unexpected request id: %s", response.RequestID)
	}
	data, _ := response.Result["data"].([]any)
	item, _ := data[0].(map[string]any)
	if response.Result["upstream_task_id"] != nil || item["url"] != "https://example.com/deyun.mp4" {
		t.Fatalf("unexpected response: %+v", response.Result)
	}
}

func TestNormalizeVolcesCompatibleResultPreservesNativeResponse(t *testing.T) {
	native := map[string]any{"id": "native-task", "status": "queued"}
	got, requestID, err := normalizeVolcesCompatibleResult(native)
	if err != nil {
		t.Fatalf("normalize native response: %v", err)
	}
	if got["id"] != "native-task" || requestID != "" {
		t.Fatalf("native response changed unexpectedly: %+v requestID=%q", got, requestID)
	}
}

func TestNormalizeVolcesCompatibleResultRejectsBusinessError(t *testing.T) {
	_, requestID, err := normalizeVolcesCompatibleResult(map[string]any{
		"code":       1004,
		"message":    "Authorization is expired",
		"request_id": "deyun-error-request",
	})
	if err == nil {
		t.Fatal("expected business error")
	}
	if requestID != "deyun-error-request" || ErrorCode(err) != "volces_1004" {
		t.Fatalf("unexpected error metadata requestID=%q code=%q err=%v", requestID, ErrorCode(err), err)
	}
	if !strings.Contains(err.Error(), "Authorization is expired") {
		t.Fatalf("unexpected error message: %v", err)
	}
}

func TestNormalizeVolcesCompatibleResultRejectsHTTP200ErrorObject(t *testing.T) {
	_, _, err := normalizeVolcesCompatibleResult(map[string]any{
		"error": map[string]any{
			"code":    "ModelNotOpen",
			"message": "model service is not activated",
			"type":    "Not Found",
		},
	})
	if err == nil {
		t.Fatal("expected HTTP 200 error object to fail")
	}
	if ErrorCode(err) != "ModelNotOpen" || !strings.Contains(err.Error(), "not activated") {
		t.Fatalf("unexpected error: code=%q err=%v", ErrorCode(err), err)
	}
}
