package sdlc

import (
	"testing"
	"time"
)

func TestNewArtifact(t *testing.T) {
	tests := []struct {
		artType  ArtifactType
		wantPath string
	}{
		{ArtifactSpec, "spec.md"},
		{ArtifactDesign, "design.md"},
		{ArtifactTasks, "tasks.md"},
		{ArtifactQAPlan, "qa-plan.md"},
		{ArtifactReview, "review.md"},
		{ArtifactAudit, "audit.md"},
		{ArtifactQAResults, "qa-results.md"},
	}

	for _, tt := range tests {
		t.Run(string(tt.artType), func(t *testing.T) {
			art := NewArtifact(tt.artType)
			if art.Status != StatusPending {
				t.Errorf("NewArtifact() status = %v, want %v", art.Status, StatusPending)
			}
			if art.Path != tt.wantPath {
				t.Errorf("NewArtifact() path = %v, want %v", art.Path, tt.wantPath)
			}
		})
	}
}

func TestArtifact_Approve(t *testing.T) {
	art := NewArtifact(ArtifactSpec)
	art.Approve("user@example.com")

	if art.Status != StatusApproved {
		t.Errorf("Approve() status = %v, want %v", art.Status, StatusApproved)
	}
	if art.ApprovedBy != "user@example.com" {
		t.Errorf("Approve() approvedBy = %v, want %v", art.ApprovedBy, "user@example.com")
	}
	if art.ApprovedAt == nil {
		t.Error("Approve() approvedAt should not be nil")
	}
	if art.RejectedBy != "" {
		t.Errorf("Approve() should clear rejectedBy, got %v", art.RejectedBy)
	}
	if art.RejectedAt != nil {
		t.Error("Approve() should clear rejectedAt")
	}
}

func TestArtifact_Reject(t *testing.T) {
	art := NewArtifact(ArtifactSpec)
	art.Reject("reviewer@example.com")

	if art.Status != StatusRejected {
		t.Errorf("Reject() status = %v, want %v", art.Status, StatusRejected)
	}
	if art.RejectedBy != "reviewer@example.com" {
		t.Errorf("Reject() rejectedBy = %v, want %v", art.RejectedBy, "reviewer@example.com")
	}
	if art.RejectedAt == nil {
		t.Error("Reject() rejectedAt should not be nil")
	}
}

func TestArtifact_ApproveAfterReject(t *testing.T) {
	art := NewArtifact(ArtifactSpec)

	// First reject
	art.Reject("reviewer@example.com")
	if art.Status != StatusRejected {
		t.Fatalf("expected rejected status after Reject()")
	}

	// Then approve
	art.Approve("approver@example.com")
	if art.Status != StatusApproved {
		t.Errorf("Approve() after Reject() status = %v, want %v", art.Status, StatusApproved)
	}
	if art.RejectedBy != "" {
		t.Errorf("Approve() should clear rejectedBy, got %v", art.RejectedBy)
	}
	if art.RejectedAt != nil {
		t.Error("Approve() should clear rejectedAt")
	}
}

func TestArtifact_MarkDraft(t *testing.T) {
	art := NewArtifact(ArtifactSpec)
	art.MarkDraft()

	if art.Status != StatusDraft {
		t.Errorf("MarkDraft() status = %v, want %v", art.Status, StatusDraft)
	}
}

func TestArtifact_MarkPassed(t *testing.T) {
	art := NewArtifact(ArtifactQAResults)
	art.MarkPassed()

	if art.Status != StatusPassed {
		t.Errorf("MarkPassed() status = %v, want %v", art.Status, StatusPassed)
	}
}

func TestArtifact_MarkFailed(t *testing.T) {
	art := NewArtifact(ArtifactQAResults)
	art.MarkFailed()

	if art.Status != StatusFailed {
		t.Errorf("MarkFailed() status = %v, want %v", art.Status, StatusFailed)
	}
}

func TestArtifact_MarkNeedsFix(t *testing.T) {
	art := NewArtifact(ArtifactReview)
	art.MarkNeedsFix()

	if art.Status != StatusNeedsFix {
		t.Errorf("MarkNeedsFix() status = %v, want %v", art.Status, StatusNeedsFix)
	}
}

func TestArtifact_ApprovedAtTimestamp(t *testing.T) {
	art := NewArtifact(ArtifactSpec)
	before := time.Now().UTC()
	art.Approve("user@example.com")
	after := time.Now().UTC()

	if art.ApprovedAt.Before(before) || art.ApprovedAt.After(after) {
		t.Errorf("ApprovedAt %v not in expected range [%v, %v]", art.ApprovedAt, before, after)
	}
}

func TestArtifact_RejectedAtTimestamp(t *testing.T) {
	art := NewArtifact(ArtifactSpec)
	before := time.Now().UTC()
	art.Reject("user@example.com")
	after := time.Now().UTC()

	if art.RejectedAt.Before(before) || art.RejectedAt.After(after) {
		t.Errorf("RejectedAt %v not in expected range [%v, %v]", art.RejectedAt, before, after)
	}
}
