package ucca

import (
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v3"
)

// PolicyEngine evaluates intakes against YAML-defined rules
type PolicyEngine struct {
	config *PolicyConfig
}

// NewPolicyEngine creates a new policy engine, loading from the default path.
// It searches for the policy file in common locations.
func NewPolicyEngine() (*PolicyEngine, error) {
	searchPaths := []string{
		DefaultPolicyPath,
		filepath.Join(".", "policies", "ucca_policy_v1.yaml"),
		filepath.Join("..", "policies", "ucca_policy_v1.yaml"),
		filepath.Join("..", "..", "policies", "ucca_policy_v1.yaml"),
		"/app/policies/ucca_policy_v1.yaml",
	}

	var data []byte
	var err error
	for _, path := range searchPaths {
		data, err = os.ReadFile(path)
		if err == nil {
			break
		}
	}

	if err != nil {
		return nil, fmt.Errorf("failed to load policy from any known location: %w", err)
	}

	var config PolicyConfig
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse policy YAML: %w", err)
	}

	return &PolicyEngine{config: &config}, nil
}

// NewPolicyEngineFromPath loads policy from a specific file path
func NewPolicyEngineFromPath(path string) (*PolicyEngine, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read policy file: %w", err)
	}

	var config PolicyConfig
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse policy YAML: %w", err)
	}

	return &PolicyEngine{config: &config}, nil
}

// GetPolicyVersion returns the policy version
func (e *PolicyEngine) GetPolicyVersion() string {
	return e.config.Policy.Version
}

// GetAllRules returns all rules in the policy
func (e *PolicyEngine) GetAllRules() []RuleDef {
	return e.config.Rules
}

// GetAllPatterns returns all patterns in the policy
func (e *PolicyEngine) GetAllPatterns() map[string]PatternDef {
	return e.config.Patterns
}

// GetAllControls returns all controls in the policy
func (e *PolicyEngine) GetAllControls() map[string]ControlDef {
	return e.config.Controls
}

// GetProblemSolutions returns problem-solution mappings
func (e *PolicyEngine) GetProblemSolutions() []ProblemSolutionDef {
	return e.config.ProblemSolutions
}
