package configrefresh_test

import (
	"context"
	"testing"

	"iop/apps/edge/internal/configrefresh"
	"iop/packages/go/config"
)

// TestClassifyProviderCapacityApplied verifies S07: provider capacity change is classified as applied.
func TestClassifyProviderCapacityApplied(t *testing.T) {
	dir := t.TempDir()

	currentPath := writeYAML(t, dir, "current.yaml", baseEdgeYAML)
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 8
        max_queue: 4
        queue_timeout_ms: 5000
 `
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)

	ctx := context.Background()
	result, _, err := configrefresh.Evaluate(ctx, current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-s07",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusApplied {
		t.Errorf("expected status=%q, got %q (summary: %s)", configrefresh.StatusApplied, result.Status, result.Summary)
	}
	if len(result.Changes) == 0 {
		t.Fatalf("expected at least one change")
	}
	found := false
	for _, c := range result.Changes {
		if c.Class == configrefresh.StatusApplied {
			found = true
		}
		if c.Class == configrefresh.StatusRestartRequired {
			t.Errorf("unexpected restart_required change: %s", c.Path)
		}
	}
	if !found {
		t.Errorf("no applied change found in: %+v", result.Changes)
	}
}

func TestClassifyProviderStructuralChangeRestartRequired(t *testing.T) {
	dir := t.TempDir()
	currentPath := writeYAML(t, dir, "current.yaml", baseEdgeYAML)
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
      openai_compat:
        enabled: true
        provider: "openai"
        endpoint: "http://127.0.0.1:9000/v1"
    providers:
      - id: "prov-a"
        type: "openai_compat"
        category: "api"
        adapter: "openai_compat"
        models: ["llama3.1"]
        capacity: 2
        max_queue: 4
        queue_timeout_ms: 5000
 `
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)

	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-provider-structural",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusRestartRequired {
		t.Fatalf("expected status=%q, got %q changes=%+v", configrefresh.StatusRestartRequired, result.Status, result.Changes)
	}
	found := false
	for _, change := range result.Changes {
		if change.Path == `nodes[].providers["prov-a"].type` && change.Class == configrefresh.StatusRestartRequired {
			found = true
		}
	}
	if !found {
		t.Fatalf("provider structural type change not found in %+v", result.Changes)
	}
}

func TestClassifyProtocolProfileChangeRestartRequired(t *testing.T) {
	current := &config.EdgeConfig{ProtocolProfiles: map[string]config.ProtocolProfileConf{
		"custom": {Base: "openai", ModelMapping: map[string]string{"canonical": "upstream-a"}},
	}}
	candidate := &config.EdgeConfig{ProtocolProfiles: map[string]config.ProtocolProfileConf{
		"custom": {Base: "openai", ModelMapping: map[string]string{"canonical": "upstream-b"}},
	}}
	result := configrefresh.Classify(current, candidate)
	if result.Status != configrefresh.StatusRestartRequired {
		t.Fatalf("status = %q, want restart_required; changes=%+v", result.Status, result.Changes)
	}
	found := false
	for _, change := range result.Changes {
		if change.Path == "protocol_profiles" && change.Class == configrefresh.StatusRestartRequired {
			found = true
		}
	}
	if !found {
		t.Fatalf("protocol_profiles restart path missing: %+v", result.Changes)
	}
}

func TestClassifyProviderProfileSelectorRestartRequired(t *testing.T) {
	provider := config.NodeProviderConf{ID: "provider-a", Profile: "profile-a"}
	current := &config.EdgeConfig{Nodes: []config.NodeDefinition{{ID: "node-a", Providers: []config.NodeProviderConf{provider}}}}
	provider.Profile = "profile-b"
	candidate := &config.EdgeConfig{Nodes: []config.NodeDefinition{{ID: "node-a", Providers: []config.NodeProviderConf{provider}}}}
	result := configrefresh.Classify(current, candidate)
	wantPath := `nodes[].providers["provider-a"].profile`
	for _, change := range result.Changes {
		if change.Path == wantPath && change.Class == configrefresh.StatusRestartRequired {
			return
		}
	}
	t.Fatalf("profile selector restart path missing: %+v", result.Changes)
}

// TestRefreshInvalidProviderRejected verifies S09: invalid provider config is classified as rejected.
func TestRefreshInvalidProviderRejected(t *testing.T) {
	dir := t.TempDir()
	currentPath := writeYAML(t, dir, "current.yaml", baseEdgeYAML)
	// Invalid: shared validator rejects enabled openai_compat without endpoint.
	invalidProviderYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      openai_compat:
        enabled: true
        endpoint: ""
 `
	invalidPath := writeYAML(t, dir, "invalid_provider.yaml", invalidProviderYAML)

	current := buildNormalizedCurrent(t, currentPath)

	ctx := context.Background()
	result, candidate, err := configrefresh.Evaluate(ctx, current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: invalidPath,
		RequestID:  "test-s09-provider",
	})
	if err != nil {
		t.Fatalf("Evaluate should not return error for rejected config: %v", err)
	}
	if result.Status != configrefresh.StatusRejected {
		t.Errorf("expected status=%q, got %q (summary: %s)", configrefresh.StatusRejected, result.Status, result.Summary)
	}
	if candidate != nil {
		t.Errorf("expected nil candidate for rejected result")
	}
}

// TestClassifyProviderEnabledLiveApply verifies that toggling providers[].enabled
// is classified as StatusApplied (live apply, no restart required).
func TestClassifyProviderEnabledLiveApply(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	// Candidate disables prov-a.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        enabled: false
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-enabled-liveapply",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusApplied {
		t.Fatalf("expected status=applied for enabled toggle, got %q", result.Status)
	}
	foundEnabled := false
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-a"].enabled` {
			foundEnabled = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("providers[].enabled class: got %q, want applied", c.Class)
			}
			if c.Previous != "true" || c.Next != "false" {
				t.Errorf("providers[].enabled change: prev=%q next=%q", c.Previous, c.Next)
			}
		}
		if c.Class == configrefresh.StatusRestartRequired {
			t.Errorf("unexpected restart_required change for enabled-only diff: %s", c.Path)
		}
	}
	if !foundEnabled {
		t.Errorf("providers[].enabled change path not found in: %+v", result.Changes)
	}
}

// TestClassifyProviderFirstEndpointOnlyRestartRequired verifies that changing
// only the provider endpoint (type/category unchanged) is classified as
// restart_required and surfaces the correct path.
func TestClassifyProviderFirstEndpointOnlyRestartRequired(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    providers:
      - id: "prov-oc"
        type: "openai_compat"
        category: "api"
        endpoint: "http://127.0.0.1:8000/v1"
        models: ["model-a"]
        capacity: 2
`
	// Only endpoint changes — type, category, models, capacity are identical.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    providers:
      - id: "prov-oc"
        type: "openai_compat"
        category: "api"
        endpoint: "http://127.0.0.1:9000/v1"
        models: ["model-a"]
        capacity: 2
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-endpoint-only",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusRestartRequired {
		t.Fatalf("expected status=restart_required for endpoint-only change, got %q; changes=%+v", result.Status, result.Changes)
	}
	found := false
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-oc"].endpoint` && c.Class == configrefresh.StatusRestartRequired {
			found = true
		}
	}
	if !found {
		t.Errorf("expected restart_required change for providers[].endpoint; changes=%+v", result.Changes)
	}
}

// TestClassifyProviderFirstHeadersChangeRestartRequired verifies that changing
// a provider headers map (type/category unchanged) is classified as
// restart_required — covers map deep-diff path.
func TestClassifyProviderFirstHeadersChangeRestartRequired(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    providers:
      - id: "prov-oc"
        type: "openai_compat"
        category: "api"
        endpoint: "http://127.0.0.1:8000/v1"
        headers:
          Authorization: "Bearer old-token"
        models: ["model-a"]
        capacity: 2
`
	// Only headers change.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    providers:
      - id: "prov-oc"
        type: "openai_compat"
        category: "api"
        endpoint: "http://127.0.0.1:8000/v1"
        headers:
          Authorization: "Bearer new-token"
        models: ["model-a"]
        capacity: 2
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-headers-only",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusRestartRequired {
		t.Fatalf("expected status=restart_required for headers change, got %q; changes=%+v", result.Status, result.Changes)
	}
	found := false
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-oc"].headers` && c.Class == configrefresh.StatusRestartRequired {
			found = true
		}
	}
	if !found {
		t.Errorf("expected restart_required change for providers[].headers; changes=%+v", result.Changes)
	}
}

func TestClassifyProviderFirstExecutionFieldRestartRequired(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      vllm:
        enabled: true
        endpoint: "http://127.0.0.1:8000/v1"
    providers:
      - id: "prov-vllm"
        type: "vllm"
        category: "api"
        endpoint: "http://127.0.0.1:8000/v1"
        models: ["model-a"]
        capacity: 2
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	// Candidate changes endpoint (provider-first execution field) → restart required.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      vllm:
        enabled: true
        endpoint: "http://127.0.0.1:8080/v1"
    providers:
      - id: "prov-vllm"
        type: "openai_compat"
        category: "api"
        endpoint: "http://127.0.0.1:8080/v1"
        models: ["model-a"]
        capacity: 2
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-provfirst-restart",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusRestartRequired {
		t.Fatalf("expected status=restart_required for provider type change, got %q", result.Status)
	}
	hasTypeRestart := false
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-vllm"].type` && c.Class == configrefresh.StatusRestartRequired {
			hasTypeRestart = true
		}
	}
	if !hasTypeRestart {
		t.Errorf("expected restart_required for providers[].type change; changes: %+v", result.Changes)
	}
}

// TestClassifyProviderPriorityApplied verifies that provider priority change
// is classified as StatusApplied (live apply, no restart required).
func TestClassifyProviderPriorityApplied(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        priority: 5
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	// Candidate only changes priority.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        priority: 1
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-priority-applied",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusApplied {
		t.Fatalf("expected status=applied for priority-only change, got %q (summary: %s)", result.Status, result.Summary)
	}
	foundPriority := false
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-a"].priority` {
			foundPriority = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("providers[].priority class: got %q, want applied", c.Class)
			}
			if c.Previous != "5" || c.Next != "1" {
				t.Errorf("providers[].priority change: prev=%q next=%q", c.Previous, c.Next)
			}
		}
		if c.Class == configrefresh.StatusRestartRequired {
			t.Errorf("unexpected restart_required change for priority-only diff: %s", c.Path)
		}
	}
	if !foundPriority {
		t.Errorf("providers[].priority change path not found in: %+v", result.Changes)
	}
}

// TestClassifyProviderLongContextCapacityApplied verifies that provider
// total_context_tokens and long_context_capacity changes are classified as
// live-apply (StatusApplied), consistent with capacity/priority.
func TestClassifyProviderLongContextCapacityApplied(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        total_context_tokens: 262144
        long_context_capacity: 1
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	// Candidate only changes the two long-context fields.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        total_context_tokens: 524288
        long_context_capacity: 2
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-long-capacity-applied",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusApplied {
		t.Fatalf("expected status=applied for long-context-only change, got %q (summary: %s)", result.Status, result.Summary)
	}
	foundTotal := false
	foundLong := false
	for _, c := range result.Changes {
		switch c.Path {
		case `nodes[].providers["prov-a"].total_context_tokens`:
			foundTotal = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("total_context_tokens class: got %q, want applied", c.Class)
			}
			if c.Previous != "262144" || c.Next != "524288" {
				t.Errorf("total_context_tokens change: prev=%q next=%q", c.Previous, c.Next)
			}
		case `nodes[].providers["prov-a"].long_context_capacity`:
			foundLong = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("long_context_capacity class: got %q, want applied", c.Class)
			}
			if c.Previous != "1" || c.Next != "2" {
				t.Errorf("long_context_capacity change: prev=%q next=%q", c.Previous, c.Next)
			}
		}
		if c.Class == configrefresh.StatusRestartRequired {
			t.Errorf("unexpected restart_required change for long-context-only diff: %s", c.Path)
		}
	}
	if !foundTotal {
		t.Errorf("providers[].total_context_tokens change path not found in: %+v", result.Changes)
	}
	if !foundLong {
		t.Errorf("providers[].long_context_capacity change path not found in: %+v", result.Changes)
	}
}

// TestClassifyProviderPoolPolicyLiveApply verifies that changes to the
// canonical root provider_pool.max_queue and provider_pool.queue_timeout_ms
// are classified as live-apply (StatusApplied) at the root path.
func TestClassifyProviderPoolPolicyLiveApply(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
provider_pool:
  max_queue: 16
  queue_timeout_ms: 30000
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
provider_pool:
  max_queue: 32
  queue_timeout_ms: 60000
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-pool-policy-liveapply",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	if result.Status != configrefresh.StatusApplied {
		t.Fatalf("expected status=applied for root provider_pool change, got %q (summary: %s)", result.Status, result.Summary)
	}
	foundMaxQ := false
	foundTimeout := false
	for _, c := range result.Changes {
		switch c.Path {
		case "provider_pool.max_queue":
			foundMaxQ = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("provider_pool.max_queue class: got %q, want applied", c.Class)
			}
			if c.Previous != "16" || c.Next != "32" {
				t.Errorf("provider_pool.max_queue change: prev=%q next=%q", c.Previous, c.Next)
			}
		case "provider_pool.queue_timeout_ms":
			foundTimeout = true
			if c.Class != configrefresh.StatusApplied {
				t.Errorf("provider_pool.queue_timeout_ms class: got %q, want applied", c.Class)
			}
			if c.Previous != "30000" || c.Next != "60000" {
				t.Errorf("provider_pool.queue_timeout_ms change: prev=%q next=%q", c.Previous, c.Next)
			}
		}
		if c.Class == configrefresh.StatusRestartRequired {
			t.Errorf("unexpected restart_required change for policy-only diff: %s", c.Path)
		}
	}
	if !foundMaxQ {
		t.Errorf("provider_pool.max_queue change not found in: %+v", result.Changes)
	}
	if !foundTimeout {
		t.Errorf("provider_pool.queue_timeout_ms change not found in: %+v", result.Changes)
	}
}

// TestClassifyProviderPoolPolicyIgnoresLegacyWhenCanonical verifies that when
// canonical provider_pool is set, per-provider max_queue/queue_timeout_ms
// changes are not reported as effective policy changes.
func TestClassifyProviderPoolPolicyIgnoresLegacyWhenCanonical(t *testing.T) {
	dir := t.TempDir()
	currentYAML := `
server:
  listen: "0.0.0.0:9090"
provider_pool:
  max_queue: 16
  queue_timeout_ms: 30000
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        max_queue: 4
        queue_timeout_ms: 5000
`
	currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
	// Candidate changes only the legacy per-provider queue fields while
	// canonical provider_pool remains identical.
	candidateYAML := `
server:
  listen: "0.0.0.0:9090"
provider_pool:
  max_queue: 16
  queue_timeout_ms: 30000
nodes:
  - id: "node-1"
    alias: "n1"
    token: "tok-1"
    adapters:
      ollama:
        enabled: true
        base_url: "http://127.0.0.1:11434"
    providers:
      - id: "prov-a"
        type: "ollama"
        category: "local_inference"
        adapter: "ollama"
        models: ["llama3.1"]
        capacity: 2
        max_queue: 8
        queue_timeout_ms: 10000
`
	candidatePath := writeYAML(t, dir, "candidate.yaml", candidateYAML)

	current := buildNormalizedCurrent(t, currentPath)
	result, _, err := configrefresh.Evaluate(context.Background(), current, configrefresh.Request{
		Mode:       configrefresh.ModeDryRun,
		ConfigPath: candidatePath,
		RequestID:  "test-policy-ignores-legacy",
	})
	if err != nil {
		t.Fatalf("Evaluate: %v", err)
	}
	for _, c := range result.Changes {
		if c.Path == `nodes[].providers["prov-a"].max_queue` {
			t.Errorf("legacy per-provider max_queue should not be reported as policy change; got change: %+v", c)
		}
		if c.Path == `nodes[].providers["prov-a"].queue_timeout_ms` {
			t.Errorf("legacy per-provider queue_timeout_ms should not be reported as policy change; got change: %+v", c)
		}
	}
}
