package clients

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

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

func TestKelingOmniPayloadPreservesCompatibleSettings(t *testing.T) {
	payload, cleanupIDs, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
		Kind:      "videos.generations",
		ModelType: "omni_video",
		Body: map[string]any{
			"prompt":           "A product reveal",
			"duration":         3,
			"resolution":       "720p",
			"aspect_ratio":     "16:9",
			"audio":            false,
			"watermark_info":   map[string]any{"enabled": true},
			"external_task_id": "external-1",
		},
		Candidate: store.RuntimeModelCandidate{
			Provider:          "keling",
			ProviderModelName: "kling-video-o1",
			Capabilities:      map[string]any{"omni_video": map[string]any{}},
		},
	}, "token")
	if err != nil {
		t.Fatalf("build compatible Omni payload: %v", err)
	}
	if len(cleanupIDs) != 0 ||
		payload["model_name"] != "kling-video-o1" ||
		payload["mode"] != "std" ||
		payload["sound"] != "off" ||
		payload["duration"] != "3" ||
		payload["aspect_ratio"] != "16:9" ||
		payload["external_task_id"] != "external-1" {
		t.Fatalf("unexpected compatible Omni payload: %+v", payload)
	}
	watermark, _ := payload["watermark_info"].(map[string]any)
	if watermark["enabled"] != true {
		t.Fatalf("watermark setting was not preserved: %+v", payload)
	}
}

func TestKelingOmniUpstreamModelNameSeparatesGatewayAliases(t *testing.T) {
	tests := map[string]string{
		"kling-o1":       "kling-video-o1",
		"kling-video-o1": "kling-video-o1",
		"kling-3.0-omni": "kling-v3-omni",
		"kling-v3-omni":  "kling-v3-omni",
	}
	for configured, want := range tests {
		got := kelingOmniUpstreamModelName(store.RuntimeModelCandidate{ProviderModelName: configured})
		if got != want {
			t.Fatalf("configured=%s got=%s want=%s", configured, got, want)
		}
	}
}

func TestKelingOmniRejectsGeneratedAudioForO1(t *testing.T) {
	_, _, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
		Body: map[string]any{
			"prompt":       "A beach",
			"duration":     5,
			"resolution":   "1080p",
			"aspect_ratio": "9:16",
			"audio":        true,
		},
		Candidate: store.RuntimeModelCandidate{ProviderModelName: "kling-video-o1"},
	}, "token")
	if err == nil || ErrorCode(err) != "invalid_parameter" {
		t.Fatalf("expected generated-audio rejection for O1, got %v", err)
	}
}

func TestKelingOmniResumeReturnsUpstreamFailureCodeAndModel(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet || r.URL.Path != "/videos/omni-video/remote-failed" {
			t.Fatalf("unexpected request %s %s", r.Method, r.URL.Path)
		}
		if r.Header.Get("Authorization") != "Bearer upstream-key" {
			t.Fatalf("unexpected Authorization header: %q", r.Header.Get("Authorization"))
		}
		_ = json.NewEncoder(w).Encode(map[string]any{
			"code":       0,
			"request_id": "failure-request",
			"data": map[string]any{
				"task_id":         "remote-failed",
				"task_status":     "failed",
				"task_status_msg": "content policy rejection",
			},
		})
	}))
	defer server.Close()

	_, err := (KelingClient{HTTPClient: server.Client()}).Run(context.Background(), Request{
		Kind:              "videos.generations",
		ModelType:         "omni_video",
		RemoteTaskID:      "remote-failed",
		RemoteTaskPayload: map[string]any{"endpoint": "/videos/omni-video"},
		Candidate: store.RuntimeModelCandidate{
			BaseURL:           server.URL,
			Provider:          "keling",
			ProviderModelName: "kling-v3-omni",
			Credentials:       map[string]any{"apiKey": "upstream-key"},
			PlatformConfig: map[string]any{
				"kelingPollIntervalMs":     10,
				"kelingPollTimeoutSeconds": 1,
			},
		},
	})
	if err == nil || ErrorCode(err) != "keling_task_failed" || !strings.Contains(err.Error(), "content policy rejection") {
		t.Fatalf("expected preserved Keling task failure, got code=%q err=%v", ErrorCode(err), err)
	}
}

func TestKelingOmniPayloadPreservesIntelligentMultiShot(t *testing.T) {
	payload, _, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
		Kind:      "videos.generations",
		ModelType: "omni_video",
		Body: map[string]any{
			"prompt":       "Create three coherent shots",
			"duration":     5,
			"resolution":   "1080p",
			"aspect_ratio": "9:16",
			"multi_shot":   true,
			"shot_type":    "intelligence",
		},
		Candidate: store.RuntimeModelCandidate{
			ProviderModelName: "kling-v3-omni",
			Capabilities:      map[string]any{"omni_video": map[string]any{}},
		},
	}, "token")
	if err != nil {
		t.Fatalf("build intelligent multi-shot payload: %v", err)
	}
	if payload["multi_shot"] != true || payload["shot_type"] != "intelligence" || payload["prompt"] != "Create three coherent shots" {
		t.Fatalf("unexpected intelligent multi-shot payload: %+v", payload)
	}
}

func TestKelingVideoSuccessResultPreservesOfficialVideoMetadata(t *testing.T) {
	result := kelingVideoSuccessResult(Request{Candidate: store.RuntimeModelCandidate{ProviderModelName: "kling-video-o1"}}, "remote-1", map[string]any{
		"data": map[string]any{
			"task_result": map[string]any{
				"videos": []any{map[string]any{
					"id":            "video-1",
					"url":           "https://example.com/video.mp4",
					"watermark_url": "https://example.com/watermarked.mp4",
					"duration":      "3",
				}},
			},
		},
	})
	data, _ := result["data"].([]any)
	video, _ := data[0].(map[string]any)
	if video["id"] != "video-1" || video["watermark_url"] != "https://example.com/watermarked.mp4" || video["duration"] != "3" {
		t.Fatalf("official video metadata was lost: %+v", video)
	}
}
