package tools

import (
	"os"
	"path/filepath"
	"testing"
)

func TestDetectAnomalies_LabelMismatch(t *testing.T) {
	dir := t.TempDir()

	// Same time range, different calltypes across two models
	data := `[{"Operator":"test"},` +
		`[0,10,100,1000,[{"species":"Kiwi","calltype":"Duet","certainty":100,"filter":"model-a"},` +
		`{"species":"Kiwi","calltype":"Male","certainty":100,"filter":"model-b"}]]]`
	if err := os.WriteFile(filepath.Join(dir, "f1.data"), []byte(data), 0644); err != nil {
		t.Fatal(err)
	}

	out, err := DetectAnomalies(DetectAnomaliesInput{Folder: dir, Models: []string{"model-a", "model-b"}})
	if err != nil {
		t.Fatal(err)
	}
	if out.LabelMismatches != 1 {
		t.Errorf("expected 1 label mismatch, got %d", out.LabelMismatches)
	}
	if out.CertaintyMismatches != 0 {
		t.Errorf("expected 0 certainty mismatches, got %d", out.CertaintyMismatches)
	}
	if out.Anomalies[0].Type != "label_mismatch" {
		t.Errorf("expected label_mismatch, got %s", out.Anomalies[0].Type)
	}
}

func TestDetectAnomalies_CertaintyMismatch(t *testing.T) {
	dir := t.TempDir()

	// Same time range, same labels, different certainty
	data := `[{"Operator":"test"},` +
		`[0,10,100,1000,[{"species":"Kiwi","calltype":"Duet","certainty":90,"filter":"model-a"},` +
		`{"species":"Kiwi","calltype":"Duet","certainty":100,"filter":"model-b"}]]]`
	if err := os.WriteFile(filepath.Join(dir, "f1.data"), []byte(data), 0644); err != nil {
		t.Fatal(err)
	}

	out, err := DetectAnomalies(DetectAnomaliesInput{Folder: dir, Models: []string{"model-a", "model-b"}})
	if err != nil {
		t.Fatal(err)
	}
	if out.CertaintyMismatches != 1 {
		t.Errorf("expected 1 certainty mismatch, got %d", out.CertaintyMismatches)
	}
	if out.LabelMismatches != 0 {
		t.Errorf("expected 0 label mismatches, got %d", out.LabelMismatches)
	}
}

func TestDetectAnomalies_NoAnomalyWhenAgreement(t *testing.T) {
	dir := t.TempDir()

	data := `[{"Operator":"test"},` +
		`[0,10,100,1000,[{"species":"Kiwi","calltype":"Duet","certainty":100,"filter":"model-a"},` +
		`{"species":"Kiwi","calltype":"Duet","certainty":100,"filter":"model-b"}]]]`
	if err := os.WriteFile(filepath.Join(dir, "f1.data"), []byte(data), 0644); err != nil {
		t.Fatal(err)
	}

	out, err := DetectAnomalies(DetectAnomaliesInput{Folder: dir, Models: []string{"model-a", "model-b"}})
	if err != nil {
		t.Fatal(err)
	}
	if out.AnomaliesTotal != 0 {
		t.Errorf("expected 0 anomalies, got %d", out.AnomaliesTotal)
	}
}

func TestDetectAnomalies_LonelySegmentSkipped(t *testing.T) {
	dir := t.TempDir()

	// model-a has a segment, model-b has no segment in this file
	data := `[{"Operator":"test"},` +
		`[0,10,100,1000,[{"species":"Kiwi","certainty":100,"filter":"model-a"}]]]`
	if err := os.WriteFile(filepath.Join(dir, "f1.data"), []byte(data), 0644); err != nil {
		t.Fatal(err)
	}

	out, err := DetectAnomalies(DetectAnomaliesInput{Folder: dir, Models: []string{"model-a", "model-b"}})
	if err != nil {
		t.Fatal(err)
	}
	if out.AnomaliesTotal != 0 {
		t.Errorf("lonely segment should be skipped, got %d anomalies", out.AnomaliesTotal)
	}
	if out.FilesWithAllModels != 0 {
		t.Errorf("file missing a model should not count as FilesWithAllModels")
	}
}

func TestDetectAnomalies_FailsWithOneModel(t *testing.T) {
	dir := t.TempDir()
	_, err := DetectAnomalies(DetectAnomaliesInput{Folder: dir, Models: []string{"model-a"}})
	if err == nil {
		t.Error("expected error with only 1 model")
	}
}