package ml

import (
	"math"
	"testing"
)

func TestSdcliParseProgress_StandardFormat(t *testing.T) {
	line := "  3/30 |  0.84it/s |  10%"
	got, ok := SdcliParseProgress(line)
	if !ok {
		t.Fatalf("expected match, got false")
	}
	if got.Step != 3 {
		t.Errorf("Step: got %d, want 3", got.Step)
	}
	if got.TotalSteps != 30 {
		t.Errorf("TotalSteps: got %d, want 30", got.TotalSteps)
	}
	if math.Abs(got.ItPerSec-0.84) > 1e-9 {
		t.Errorf("ItPerSec: got %v, want 0.84", got.ItPerSec)
	}
	if math.Abs(got.Percent-10.0) > 1e-9 {
		t.Errorf("Percent: got %v, want 10.0", got.Percent)
	}
}

func TestSdcliParseProgress_NoMatch(t *testing.T) {
	cases := []string{
		"loading model...",
		"",
		"error: out of memory",
		"clip model loaded",
		"generating image...",
	}
	for _, line := range cases {
		_, ok := SdcliParseProgress(line)
		if ok {
			t.Errorf("expected no match for %q, but got match", line)
		}
	}
}

func TestSdcliParseProgress_AltFormat(t *testing.T) {
	t.Run("formato sampling verbose", func(t *testing.T) {
		line := "sampling: step 3 of 30 (0.84 it/s)"
		got, ok := SdcliParseProgress(line)
		if !ok {
			t.Fatalf("expected match, got false")
		}
		if got.Step != 3 {
			t.Errorf("Step: got %d, want 3", got.Step)
		}
		if got.TotalSteps != 30 {
			t.Errorf("TotalSteps: got %d, want 30", got.TotalSteps)
		}
		if math.Abs(got.ItPerSec-0.84) > 1e-9 {
			t.Errorf("ItPerSec: got %v, want 0.84", got.ItPerSec)
		}
		expectedPct := 100.0 * 3.0 / 30.0
		if math.Abs(got.Percent-expectedPct) > 1e-6 {
			t.Errorf("Percent: got %v, want %v", got.Percent, expectedPct)
		}
	})

	t.Run("formato step/total sin velocidad", func(t *testing.T) {
		line := "progress: 15/20"
		got, ok := SdcliParseProgress(line)
		if !ok {
			t.Fatalf("expected match, got false")
		}
		if got.Step != 15 {
			t.Errorf("Step: got %d, want 15", got.Step)
		}
		if got.TotalSteps != 20 {
			t.Errorf("TotalSteps: got %d, want 20", got.TotalSteps)
		}
		if got.ItPerSec != 0 {
			t.Errorf("ItPerSec: got %v, want 0", got.ItPerSec)
		}
		expectedPct := 75.0
		if math.Abs(got.Percent-expectedPct) > 1e-6 {
			t.Errorf("Percent: got %v, want %v", got.Percent, expectedPct)
		}
	})

	t.Run("formato con espacios variables y mayor velocidad", func(t *testing.T) {
		line := "  20/30 | 12.50it/s |  66%"
		got, ok := SdcliParseProgress(line)
		if !ok {
			t.Fatalf("expected match, got false")
		}
		if got.Step != 20 {
			t.Errorf("Step: got %d, want 20", got.Step)
		}
		if got.TotalSteps != 30 {
			t.Errorf("TotalSteps: got %d, want 30", got.TotalSteps)
		}
		if math.Abs(got.ItPerSec-12.5) > 1e-9 {
			t.Errorf("ItPerSec: got %v, want 12.5", got.ItPerSec)
		}
	})
}
