package config

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

	"gopkg.in/yaml.v3"

	"github.com/operator/command-center/internal/budgets"
)

// BudgetsFileName is the Phase 10 config file basename.
const BudgetsFileName = "health-budgets.yaml"

// BudgetsDocument is the on-disk shape.
type BudgetsDocument struct {
	Budgets []budgets.Budget `yaml:"budgets"`
}

// LoadBudgetsFromDir reads health-budgets.yaml from dir.
func LoadBudgetsFromDir(dir string) (*BudgetsDocument, error) {
	path := filepath.Join(dir, BudgetsFileName)
	data, err := os.ReadFile(path)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return &BudgetsDocument{}, nil
		}
		return nil, fmt.Errorf("config: read %s: %w", path, err)
	}
	return LoadBudgetsFromBytes(data)
}

// LoadBudgetsFromBytes parses + validates.
func LoadBudgetsFromBytes(data []byte) (*BudgetsDocument, error) {
	var doc BudgetsDocument
	if err := yaml.Unmarshal(data, &doc); err != nil {
		return nil, fmt.Errorf("config: budgets.yaml parse: %w", err)
	}
	seen := map[string]struct{}{}
	for i, b := range doc.Budgets {
		if b.Name == "" {
			return nil, fmt.Errorf("config: budgets[%d]: name required", i)
		}
		if b.Capacity <= 0 {
			return nil, fmt.Errorf("config: budgets[%d] (%s): capacity must be > 0", i, b.Name)
		}
		if _, dup := seen[b.Name]; dup {
			return nil, fmt.Errorf("config: duplicate budget name %q", b.Name)
		}
		seen[b.Name] = struct{}{}
	}
	return &doc, nil
}
