package cost

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestTrackLLMCost(t *testing.T) {
	tracker := NewCostTracker()
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	
	entries := tracker.GetEntries()
	assert.Equal(t, 1, len(entries))
	assert.Equal(t, "llm", entries[0].Type)
	assert.Equal(t, 0.1, entries[0].Amount) // 1000 tokens * 0.0001
}

func TestTrackGitCost(t *testing.T) {
	tracker := NewCostTracker()
	tracker.TrackGitCost("wf-1", 5)
	
	entries := tracker.GetEntries()
	assert.Equal(t, 1, len(entries))
	assert.Equal(t, "git", entries[0].Type)
}

func TestTrackComputeCost(t *testing.T) {
	tracker := NewCostTracker()
	tracker.TrackComputeCost("wf-1", "task-1", 3600000) // 1 hour in ms
	
	entries := tracker.GetEntries()
	assert.Equal(t, 1, len(entries))
	assert.Equal(t, "compute", entries[0].Type)
	assert.Equal(t, 0.5, entries[0].Amount) // 1 hour * $0.5/hour
}

func TestGetTotalCost(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackComputeCost("wf-1", "task-1", 3600000)
	
	total := tracker.GetTotalCost()
	assert.Equal(t, 0.6, total) // 0.1 + 0.5
}

func TestGetWorkflowCost(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackLLMCost("wf-2", "task-1", 2000)
	
	cost := tracker.GetWorkflowCost("wf-1")
	assert.Equal(t, 0.1, cost)
	
	cost = tracker.GetWorkflowCost("wf-2")
	assert.Equal(t, 0.2, cost)
}

func TestGetCostByType(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackLLMCost("wf-1", "task-2", 1000)
	tracker.TrackComputeCost("wf-1", "task-3", 3600000)
	
	llmCost := tracker.GetCostByType("llm")
	assert.Equal(t, 0.2, llmCost)
	
	computeCost := tracker.GetCostByType("compute")
	assert.Equal(t, 0.5, computeCost)
}

func TestGetAverageCostPerTask(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackLLMCost("wf-1", "task-2", 1000)
	
	avg := tracker.GetAverageCostPerTask("wf-1")
	assert.Equal(t, 0.1, avg)
}

func TestGetOptimizationSuggestions(t *testing.T) {
	tracker := NewCostTracker()
	
	// High LLM cost
	tracker.TrackLLMCost("wf-1", "task-1", 10000)
	tracker.TrackLLMCost("wf-1", "task-2", 10000)
	tracker.TrackComputeCost("wf-1", "task-3", 360000) // 0.1 seconds
	
	suggestions := tracker.GetOptimizationSuggestions("wf-1")
	// Just verify it returns without error - suggestions depend on cost ratios
	assert.NotNil(t, suggestions)
}

func TestGetEntriesForWorkflow(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackLLMCost("wf-2", "task-1", 1000)
	
	entries := tracker.GetEntriesForWorkflow("wf-1")
	assert.Equal(t, 1, len(entries))
}

func TestSetAndGetRate(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.SetRate("custom", 0.5)
	rate := tracker.GetRate("custom")
	
	assert.Equal(t, 0.5, rate)
}

func TestClear(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.Clear()
	
	entries := tracker.GetEntries()
	assert.Equal(t, 0, len(entries))
}

func TestMultipleCosts(t *testing.T) {
	tracker := NewCostTracker()
	
	tracker.TrackLLMCost("wf-1", "task-1", 1000)
	tracker.TrackGitCost("wf-1", 5)
	tracker.TrackComputeCost("wf-1", "task-1", 1800000) // 30 min
	
	total := tracker.GetTotalCost()
	assert.True(t, total > 0.2)
}

func TestZeroCost(t *testing.T) {
	tracker := NewCostTracker()
	
	cost := tracker.GetWorkflowCost("nonexistent")
	assert.Equal(t, 0.0, cost)
}

func BenchmarkTrackLLMCost(b *testing.B) {
	tracker := NewCostTracker()
	
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		tracker.TrackLLMCost("wf-1", "task-1", 1000)
	}
}
