package sdlc

import (
	"fmt"
	"strings"
)

// DefaultRules returns all classifier rules in priority order.
// First matching rule wins.
func DefaultRules() []Rule {
	return []Rule{
		blockedDependencyRule(),
		needsSpecRule(),
		specNeedsApprovalRule(),
		specApprovedRule(),
		needsDesignRule(),
		designNeedsApprovalRule(),
		needsTasksRule(),
		tasksNeedApprovalRule(),
		needsQAPlanRule(),
		qaPlanNeedsApprovalRule(),
		planningCompleteRule(),
		needsBranchRule(),
		readyToImplementRule(),
		implementNextTaskRule(),
		implementationCompleteRule(),
		needsReviewRule(),
		reviewHasIssuesRule(),
		reviewPassedRule(),
		needsAuditRule(),
		auditHasIssuesRule(),
		auditPassedRule(),
		needsQARule(),
		qaHasFailuresRule(),
		qaPassedRule(),
		needsMergeRule(),
		archiveFeatureRule(),
	}
}

func blockedDependencyRule() Rule {
	return Rule{
		ID: "blocked-dependency",
		Condition: func(ctx *EvalContext) bool {
			return ctx.Feature.IsBlocked()
		},
		Action: ActionBlocked,
		Message: func(ctx *EvalContext) string {
			return fmt.Sprintf("Feature blocked by: %s", strings.Join(ctx.Feature.Blockers, ", "))
		},
	}
}

func needsSpecRule() Rule {
	return Rule{
		ID: "needs-spec",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseDraft {
				return false
			}
			art := ctx.Feature.GetArtifact(ArtifactSpec)
			return art == nil || art.Status == StatusPending
		},
		Action: ActionCreateSpec,
		NextCommand: func(ctx *EvalContext) string {
			return "/spec-feature " + ctx.Feature.Slug
		},
		OutputPath: func(ctx *EvalContext) string {
			return ".sdlc/features/" + ctx.Feature.Slug + "/spec.md"
		},
	}
}

func specNeedsApprovalRule() Rule {
	return Rule{
		ID: "spec-needs-approval",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseDraft {
				return false
			}
			art := ctx.Feature.GetArtifact(ArtifactSpec)
			return art != nil && art.Status == StatusDraft
		},
		Action: ActionAwaitApproval,
		Message: func(_ *EvalContext) string {
			return "Specification requires user approval"
		},
	}
}

func specApprovedRule() Rule {
	return Rule{
		ID: "spec-approved",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseDraft {
				return false
			}
			art := ctx.Feature.GetArtifact(ArtifactSpec)
			return art != nil && art.Status == StatusApproved
		},
		Action:       ActionTransition,
		TransitionTo: PhaseSpecified,
	}
}

func needsDesignRule() Rule {
	return Rule{
		ID: "needs-design",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			art := ctx.Feature.GetArtifact(ArtifactDesign)
			return art == nil || art.Status == StatusPending
		},
		Action: ActionCreateDesign,
		NextCommand: func(ctx *EvalContext) string {
			return "/design-feature " + ctx.Feature.Slug
		},
		OutputPath: func(ctx *EvalContext) string {
			return ".sdlc/features/" + ctx.Feature.Slug + "/design.md"
		},
	}
}

func designNeedsApprovalRule() Rule {
	return Rule{
		ID: "design-needs-approval",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			art := ctx.Feature.GetArtifact(ArtifactDesign)
			return art != nil && (art.Status == StatusDraft || art.Status == StatusRejected)
		},
		Action: ActionAwaitApproval,
		Message: func(_ *EvalContext) string {
			return "Design document requires user approval"
		},
	}
}

func needsTasksRule() Rule {
	return Rule{
		ID: "needs-tasks",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			design := ctx.Feature.GetArtifact(ArtifactDesign)
			if design == nil || design.Status != StatusApproved {
				return false
			}
			tasks := ctx.Feature.GetArtifact(ArtifactTasks)
			return tasks == nil || tasks.Status == StatusPending
		},
		Action: ActionCreateTasks,
		NextCommand: func(ctx *EvalContext) string {
			return "/breakdown-feature " + ctx.Feature.Slug
		},
		OutputPath: func(ctx *EvalContext) string {
			return ".sdlc/features/" + ctx.Feature.Slug + "/tasks.md"
		},
	}
}

func tasksNeedApprovalRule() Rule {
	return Rule{
		ID: "tasks-need-approval",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			tasks := ctx.Feature.GetArtifact(ArtifactTasks)
			return tasks != nil && (tasks.Status == StatusDraft || tasks.Status == StatusRejected)
		},
		Action: ActionAwaitApproval,
		Message: func(_ *EvalContext) string {
			return "Task breakdown requires user approval"
		},
	}
}

func needsQAPlanRule() Rule {
	return Rule{
		ID: "needs-qa-plan",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			tasks := ctx.Feature.GetArtifact(ArtifactTasks)
			if tasks == nil || tasks.Status != StatusApproved {
				return false
			}
			qa := ctx.Feature.GetArtifact(ArtifactQAPlan)
			return qa == nil || qa.Status == StatusPending
		},
		Action: ActionCreateQAPlan,
		NextCommand: func(ctx *EvalContext) string {
			return "/create-qa-plan " + ctx.Feature.Slug
		},
		OutputPath: func(ctx *EvalContext) string {
			return ".sdlc/features/" + ctx.Feature.Slug + "/qa-plan.md"
		},
	}
}

func qaPlanNeedsApprovalRule() Rule {
	return Rule{
		ID: "qa-plan-needs-approval",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			qa := ctx.Feature.GetArtifact(ArtifactQAPlan)
			return qa != nil && (qa.Status == StatusDraft || qa.Status == StatusRejected)
		},
		Action: ActionAwaitApproval,
		Message: func(_ *EvalContext) string {
			return "QA plan requires user approval"
		},
	}
}

func planningCompleteRule() Rule {
	return Rule{
		ID: "planning-complete",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhaseSpecified {
				return false
			}
			qa := ctx.Feature.GetArtifact(ArtifactQAPlan)
			return qa != nil && qa.Status == StatusApproved
		},
		Action:       ActionTransition,
		TransitionTo: PhasePlanned,
	}
}

func needsBranchRule() Rule {
	return Rule{
		ID: "needs-branch",
		Condition: func(ctx *EvalContext) bool {
			if ctx.Feature.Phase != PhasePlanned {
				return false
			}
			if ctx.Config == nil || !ctx.Config.Compliance.RequireBranch {
				return false
			}
			return ctx.Feature.Branch == ""
		},
		Action: ActionCreateBranch,
		Message: func(_ *EvalContext) string {
			return "Feature branch required before implementation"
		},
		NextCommand: func(ctx *EvalContext) string {
			return "sdlc branch create " + ctx.Feature.Slug
		},
	}
}

func readyToImplementRule() Rule {
	return Rule{
		ID: "ready-to-implement",
		Condition: func(ctx *EvalContext) bool {
			// Only trigger transition for PhasePlanned -> PhaseReady
			// PhaseReady should proceed to implementNextTaskRule, not re-transition
			return ctx.Feature.Phase == PhasePlanned
		},
		Action:       ActionTransition,
		TransitionTo: PhaseReady,
		Message: func(_ *EvalContext) string {
			return "Ready for implementation: transitioning to ready phase"
		},
	}
}
