package main

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestRunApplyHostOverlayAppliesResolvedPackOverlay(t *testing.T) {
	sourceDir := t.TempDir()
	if err := os.MkdirAll(filepath.Join(sourceDir, "backend"), 0o755); err != nil {
		t.Fatalf("MkdirAll() error = %v", err)
	}
	if err := os.WriteFile(filepath.Join(sourceDir, "backend", "hello.txt"), []byte("hello\n"), 0o644); err != nil {
		t.Fatalf("WriteFile() error = %v", err)
	}

	packDir := createApplyHostOverlayPackFixture(t)
	result, err := runApplyHostOverlay(context.Background(), applyHostOverlayCLIRequest{
		PackDir:     packDir,
		ProviderID:  "kimi-a7m",
		HostVersion: "0.1.129",
		SourceDir:   sourceDir,
	})
	if err != nil {
		t.Fatalf("runApplyHostOverlay() error = %v", err)
	}

	body, err := os.ReadFile(filepath.Join(result.OutputDir, "backend", "hello.txt"))
	if err != nil {
		t.Fatalf("ReadFile() error = %v", err)
	}
	if string(body) != "patched\n" {
		t.Fatalf("patched file = %q, want %q", string(body), "patched\n")
	}
	if _, err := os.Stat(result.MetadataFilePath); err != nil {
		t.Fatalf("Stat(metadata) error = %v", err)
	}
}

func createApplyHostOverlayPackFixture(t *testing.T) string {
	t.Helper()

	packDir := t.TempDir()
	files := map[string]string{
		"pack.json": `{
  "pack_id": "openai-cn-pack",
  "version": "1.1.3",
  "vendor": "YourTeam",
  "target_host": "sub2api",
  "min_host_version": "0.1.126",
  "max_host_version": "0.2.x",
  "providers_dir": "providers",
  "checksum_file": "checksums.txt"
}`,
		"providers/kimi-a7m.json": `{
  "provider_id": "kimi-a7m",
  "display_name": "Kimi A7M OpenAI Compatible",
  "base_url": "https://kimi.a7m.com.cn/v1",
  "platform": "openai",
  "account_type": "apikey",
  "default_models": ["kimi-k2.6"],
  "smoke_test_model": "kimi-k2.6",
  "host_overlays": [
    {
      "overlay_id": "sub2api-stock-v0129-kimi-a7m",
      "display_name": "sub2api stock v0.1.129 Kimi A7M overlay",
      "target_host": "sub2api",
      "min_host_version": "0.1.129",
      "max_host_version": "0.1.129",
      "apply_mode": "patch",
      "patch_path": "overlays/kimi-a7m-sub2api-v0.1.129.patch",
      "notes_path": "overlays/kimi-a7m-sub2api-v0.1.129.md",
      "reason": "stock host still routes chat traffic into unsupported Responses path"
    }
  ],
  "group_template": {"name": "g", "rate_multiplier": 1},
  "channel_template": {"name": "c", "model_mapping": {"kimi-k2.6": "kimi-k2.6"}},
  "plan_template": {"name": "p", "price": 1, "validity_days": 30, "validity_unit": "day"},
  "import": {"supports_multi_key": true, "supports_strict": true, "supports_partial": true}
}`,
		"overlays/kimi-a7m-sub2api-v0.1.129.patch": strings.Join([]string{
			"diff --git a/backend/hello.txt b/backend/hello.txt",
			"--- a/backend/hello.txt",
			"+++ b/backend/hello.txt",
			"@@ -1 +1 @@",
			"-hello",
			"+patched",
			"",
		}, "\n"),
		"overlays/kimi-a7m-sub2api-v0.1.129.md": "# overlay\n",
	}

	checksumLines := make([]string, 0, len(files))
	for relativePath, body := range files {
		absolutePath := filepath.Join(packDir, relativePath)
		if err := os.MkdirAll(filepath.Dir(absolutePath), 0o755); err != nil {
			t.Fatalf("MkdirAll(%q) error = %v", absolutePath, err)
		}
		if err := os.WriteFile(absolutePath, []byte(body), 0o644); err != nil {
			t.Fatalf("WriteFile(%q) error = %v", absolutePath, err)
		}
		sum := sha256.Sum256([]byte(body))
		checksumLines = append(checksumLines, hex.EncodeToString(sum[:])+"  "+relativePath)
	}
	if err := os.WriteFile(filepath.Join(packDir, "checksums.txt"), []byte(strings.Join(checksumLines, "\n")+"\n"), 0o644); err != nil {
		t.Fatalf("WriteFile(checksums.txt) error = %v", err)
	}

	return packDir
}
