package sdlc

import (
	"fmt"
	"os"
	"slices"

	"gopkg.in/yaml.v3"
)

// Config represents the project SDLC configuration in .sdlc/config.yaml.
type Config struct {
	Version    int              `yaml:"version" json:"version"`
	Project    ProjectConfig    `yaml:"project" json:"project"`
	Branches   BranchConfig     `yaml:"branches" json:"branches"`
	Phases     PhaseConfig      `yaml:"phases" json:"phases"`
	Compliance ComplianceConfig `yaml:"compliance" json:"compliance"`
	Patterns   PatternsConfig   `yaml:"patterns,omitempty" json:"patterns,omitempty"` //nolint:omitzero
}

// ProjectConfig holds project-level settings.
type ProjectConfig struct {
	Name string `yaml:"name" json:"name"`
	Type string `yaml:"type,omitempty" json:"type,omitempty"`
}

// BranchConfig defines branch naming conventions.
type BranchConfig struct {
	Main          string `yaml:"main" json:"main"`
	FeaturePrefix string `yaml:"feature_prefix" json:"feature_prefix"`
}

// PhaseConfig defines which phases are enabled and what artifacts are required.
type PhaseConfig struct {
	Enabled           []FeaturePhase                  `yaml:"enabled" json:"enabled"`
	RequiredArtifacts map[FeaturePhase][]ArtifactType `yaml:"required_artifacts" json:"required_artifacts"`
}

// ComplianceConfig defines approval and gate requirements.
type ComplianceConfig struct {
	RequireApprovals bool `yaml:"require_approvals" json:"require_approvals"`
	RequireBranch    bool `yaml:"require_branch" json:"require_branch"`
	RequireQA        bool `yaml:"require_qa" json:"require_qa"`
}

// PatternsConfig defines pattern enforcement.
type PatternsConfig struct {
	AutoEnforce []string `yaml:"auto_enforce,omitempty" json:"auto_enforce,omitempty"`
}

// LoadConfig reads and parses .sdlc/config.yaml from the given project root.
func LoadConfig(root string) (*Config, error) {
	path := ConfigPath(root)
	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, ErrNotInitialized
		}
		return nil, fmt.Errorf("read config file: %w", err)
	}

	var c Config
	if err := yaml.Unmarshal(data, &c); err != nil {
		return nil, fmt.Errorf("parse config file: %w", err)
	}
	return &c, nil
}

// Save writes the config to .sdlc/config.yaml.
func (c *Config) Save(root string) error {
	data, err := yaml.Marshal(c)
	if err != nil {
		return fmt.Errorf("marshal config: %w", err)
	}

	path := ConfigPath(root)
	if err := os.WriteFile(path, data, 0o644); err != nil {
		return fmt.Errorf("write config file: %w", err)
	}
	return nil
}

// DefaultConfig returns a config with all phases enabled and standard requirements.
func DefaultConfig(projectName string) *Config {
	return &Config{
		Version: 1,
		Project: ProjectConfig{
			Name: projectName,
		},
		Branches: BranchConfig{
			Main:          "main",
			FeaturePrefix: "feature/",
		},
		Phases: PhaseConfig{
			Enabled: ValidPhases,
			RequiredArtifacts: map[FeaturePhase][]ArtifactType{
				PhaseSpecified: {ArtifactSpec},
				PhasePlanned:   {ArtifactSpec, ArtifactDesign, ArtifactTasks, ArtifactQAPlan},
				PhaseReview:    {ArtifactReview},
				PhaseAudit:     {ArtifactAudit},
				PhaseQA:        {ArtifactQAResults},
			},
		},
		Compliance: ComplianceConfig{
			RequireApprovals: true,
			RequireBranch:    true,
			RequireQA:        true,
		},
	}
}

// IsPhaseEnabled returns true if the phase is in the enabled list.
func (c *Config) IsPhaseEnabled(phase FeaturePhase) bool {
	return slices.Contains(c.Phases.Enabled, phase)
}
