package sqlite

import (
	"context"
	"database/sql"
	"errors"
	"testing"
)

func TestProviderDraftsRepoCreateGetAndList(t *testing.T) {
	store := openTestDB(t)

	id, err := store.ProviderDrafts().Create(context.Background(), ProviderDraft{
		DraftID:             "draft_001",
		PackID:              "openai-cn-pack",
		ProviderID:          "openai-zhongzhuan",
		DisplayName:         "OpenAI 中转",
		Platform:            "openai",
		BaseURL:             "https://api.example.com/v1",
		SmokeTestModel:      "gpt-5.4",
		SupportedModelsJSON: `["gpt-5.4","gpt-5.4-mini"]`,
		ManifestJSON:        `{"provider_id":"openai-zhongzhuan"}`,
		SourceHostID:        "remote43-current-host",
		Notes:               "first draft",
	})
	if err != nil {
		t.Fatalf("Create() error = %v", err)
	}
	if id <= 0 {
		t.Fatalf("Create() id = %d, want positive", id)
	}

	got, err := store.ProviderDrafts().GetByDraftID(context.Background(), "draft_001")
	if err != nil {
		t.Fatalf("GetByDraftID() error = %v", err)
	}
	if got.ProviderID != "openai-zhongzhuan" || got.DisplayName != "OpenAI 中转" {
		t.Fatalf("GetByDraftID() = %+v, want provider draft payload", got)
	}

	drafts, err := store.ProviderDrafts().List(context.Background(), ListProviderDraftsFilter{PackID: "openai-cn-pack"})
	if err != nil {
		t.Fatalf("List() error = %v", err)
	}
	if len(drafts) != 1 {
		t.Fatalf("List() len = %d, want 1", len(drafts))
	}
	if drafts[0].DraftID != "draft_001" {
		t.Fatalf("List() draft_id = %q, want draft_001", drafts[0].DraftID)
	}
}

func TestProviderDraftsRepoListSupportsQuery(t *testing.T) {
	store := openTestDB(t)

	_, err := store.ProviderDrafts().Create(context.Background(), ProviderDraft{
		DraftID:     "draft_alpha",
		PackID:      "openai-cn-pack",
		ProviderID:  "minimax-53hk",
		DisplayName: "MiniMax 53HK",
		Platform:    "openai",
	})
	if err != nil {
		t.Fatalf("Create() error = %v", err)
	}
	_, err = store.ProviderDrafts().Create(context.Background(), ProviderDraft{
		DraftID:     "draft_beta",
		PackID:      "openai-cn-pack",
		ProviderID:  "deepseek-chat-official",
		DisplayName: "DeepSeek Official",
		Platform:    "openai",
	})
	if err != nil {
		t.Fatalf("Create() second error = %v", err)
	}

	drafts, err := store.ProviderDrafts().List(context.Background(), ListProviderDraftsFilter{Query: "MiniMax"})
	if err != nil {
		t.Fatalf("List() query error = %v", err)
	}
	if len(drafts) != 1 || drafts[0].ProviderID != "minimax-53hk" {
		t.Fatalf("List() query = %+v, want only minimax-53hk", drafts)
	}
}

func TestProviderDraftsRepoUpdateByDraftID(t *testing.T) {
	store := openTestDB(t)

	_, err := store.ProviderDrafts().Create(context.Background(), ProviderDraft{
		DraftID:     "draft_update",
		PackID:      "openai-cn-pack",
		ProviderID:  "minimax-53hk",
		DisplayName: "MiniMax 53HK",
		Platform:    "openai",
	})
	if err != nil {
		t.Fatalf("Create() error = %v", err)
	}

	if err := store.ProviderDrafts().UpdateByDraftID(context.Background(), ProviderDraft{
		DraftID:             "draft_update",
		PackID:              "openai-cn-pack",
		ProviderID:          "minimax-53hk",
		DisplayName:         "MiniMax 53HK Updated",
		Platform:            "openai",
		BaseURL:             "https://api.53hk.cn/v1",
		SmokeTestModel:      "MiniMax-M2.7-highspeed",
		SupportedModelsJSON: `["MiniMax-M2.7-highspeed"]`,
		ManifestJSON:        `{"provider_id":"minimax-53hk","display_name":"MiniMax 53HK Updated"}`,
		SourceHostID:        "remote43-current-host",
		Notes:               "updated",
	}); err != nil {
		t.Fatalf("UpdateByDraftID() error = %v", err)
	}

	got, err := store.ProviderDrafts().GetByDraftID(context.Background(), "draft_update")
	if err != nil {
		t.Fatalf("GetByDraftID() error = %v", err)
	}
	if got.DisplayName != "MiniMax 53HK Updated" || got.BaseURL != "https://api.53hk.cn/v1" {
		t.Fatalf("updated draft = %+v, want updated fields", got)
	}
}

func TestProviderDraftsRepoDeleteByDraftID(t *testing.T) {
	store := openTestDB(t)

	_, err := store.ProviderDrafts().Create(context.Background(), ProviderDraft{
		DraftID:     "draft_delete",
		PackID:      "openai-cn-pack",
		ProviderID:  "deepseek-chat-official",
		DisplayName: "DeepSeek Official",
		Platform:    "openai",
	})
	if err != nil {
		t.Fatalf("Create() error = %v", err)
	}

	if err := store.ProviderDrafts().DeleteByDraftID(context.Background(), "draft_delete"); err != nil {
		t.Fatalf("DeleteByDraftID() error = %v", err)
	}
	_, err = store.ProviderDrafts().GetByDraftID(context.Background(), "draft_delete")
	if !errors.Is(err, sql.ErrNoRows) {
		t.Fatalf("GetByDraftID() after delete error = %v, want sql.ErrNoRows", err)
	}
}

func TestProviderDraftsRepoValidationErrors(t *testing.T) {
	store := openTestDB(t)

	tests := []struct {
		name  string
		draft ProviderDraft
	}{
		{"empty draft_id", ProviderDraft{PackID: "pack", ProviderID: "p", DisplayName: "n", Platform: "openai"}},
		{"empty pack_id", ProviderDraft{DraftID: "draft", ProviderID: "p", DisplayName: "n", Platform: "openai"}},
		{"empty provider_id", ProviderDraft{DraftID: "draft", PackID: "pack", DisplayName: "n", Platform: "openai"}},
		{"empty display_name", ProviderDraft{DraftID: "draft", PackID: "pack", ProviderID: "p", Platform: "openai"}},
		{"empty platform", ProviderDraft{DraftID: "draft", PackID: "pack", ProviderID: "p", DisplayName: "n"}},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			_, err := store.ProviderDrafts().Create(context.Background(), tt.draft)
			if err == nil {
				t.Fatal("Create() error = nil, want validation error")
			}
		})
	}
}

func TestProviderDraftsRepoGetByDraftIDNotFound(t *testing.T) {
	store := openTestDB(t)
	_, err := store.ProviderDrafts().GetByDraftID(context.Background(), "missing")
	if !errors.Is(err, sql.ErrNoRows) {
		t.Fatalf("GetByDraftID() error = %v, want sql.ErrNoRows", err)
	}
}
