package domain

import (
	"errors"
	"testing"
	"time"
)

func TestWorker_IsAvailable(t *testing.T) {
	tests := []struct {
		status WorkerStatus
		want   bool
	}{
		{WorkerStatusIdle, true},
		{WorkerStatusBusy, false},
		{WorkerStatusDraining, false},
		{WorkerStatusOffline, false},
	}

	for _, tt := range tests {
		t.Run(string(tt.status), func(t *testing.T) {
			w := &Worker{Status: tt.status}
			if got := w.IsAvailable(); got != tt.want {
				t.Errorf("IsAvailable() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestWorker_IsHealthy(t *testing.T) {
	threshold := 90 * time.Second

	tests := []struct {
		name          string
		lastHeartbeat time.Time
		want          bool
	}{
		{
			name:          "recent heartbeat",
			lastHeartbeat: time.Now().Add(-30 * time.Second),
			want:          true,
		},
		{
			name:          "stale heartbeat",
			lastHeartbeat: time.Now().Add(-2 * time.Minute),
			want:          false,
		},
		{
			name:          "exactly at threshold",
			lastHeartbeat: time.Now().Add(-90 * time.Second),
			want:          false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			w := &Worker{LastHeartbeat: tt.lastHeartbeat}
			if got := w.IsHealthy(threshold); got != tt.want {
				t.Errorf("IsHealthy() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestWorkerStatus_IsValid(t *testing.T) {
	tests := []struct {
		status WorkerStatus
		want   bool
	}{
		{WorkerStatusIdle, true},
		{WorkerStatusBusy, true},
		{WorkerStatusDraining, true},
		{WorkerStatusOffline, true},
		{"unknown", false},
		{"", false},
	}

	for _, tt := range tests {
		t.Run(string(tt.status), func(t *testing.T) {
			if got := tt.status.IsValid(); got != tt.want {
				t.Errorf("IsValid() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestWorker_Validate(t *testing.T) {
	tests := []struct {
		name    string
		worker  Worker
		wantErr error
	}{
		{
			name:    "valid worker",
			worker:  Worker{ID: "worker-1", Hostname: "host-1"},
			wantErr: nil,
		},
		{
			name:    "missing ID",
			worker:  Worker{Hostname: "host-1"},
			wantErr: ErrWorkerIDRequired,
		},
		{
			name:    "missing hostname",
			worker:  Worker{ID: "worker-1"},
			wantErr: ErrWorkerHostnameRequired,
		},
		{
			name:    "both missing",
			worker:  Worker{},
			wantErr: ErrWorkerIDRequired,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.worker.Validate()
			if tt.wantErr != nil {
				if !errors.Is(err, tt.wantErr) {
					t.Errorf("Validate() error = %v, want %v", err, tt.wantErr)
				}
			} else if err != nil {
				t.Errorf("Validate() unexpected error = %v", err)
			}
		})
	}
}

func TestValidWorkerStatuses(t *testing.T) {
	statuses := ValidWorkerStatuses()
	if len(statuses) != 4 {
		t.Errorf("expected 4 statuses, got %d", len(statuses))
	}

	found := make(map[WorkerStatus]bool)
	for _, s := range statuses {
		found[s] = true
	}

	expected := []WorkerStatus{WorkerStatusIdle, WorkerStatusBusy, WorkerStatusDraining, WorkerStatusOffline}
	for _, s := range expected {
		if !found[s] {
			t.Errorf("expected %s in valid statuses", s)
		}
	}
}
