// Package skillmeta validates the YAML frontmatter of the skills/ registry so
// that every SKILL.md is discoverable and structurally sound.
package skillmeta

import (
	"bytes"
	"errors"
	"fmt"

	"gopkg.in/yaml.v3"
)

// Frontmatter is the metadata block every SKILL.md carries.
type Frontmatter struct {
	Name        string   `yaml:"name"`
	Version     string   `yaml:"version"`
	Description string   `yaml:"description"`
	Metadata    Metadata `yaml:"metadata"`
}

// Metadata holds the nested metadata fields of a skill.
type Metadata struct {
	Requires Requires `yaml:"requires"`
	CLIHelp  string   `yaml:"cliHelp"`
}

// Requires lists what a skill needs to run.
type Requires struct {
	Bins []string `yaml:"bins"`
}

var errNoFrontmatter = errors.New("no `---` delimited frontmatter block")

// ExtractFrontmatter returns the YAML between the first pair of `---` fences.
func ExtractFrontmatter(src []byte) ([]byte, error) {
	const fence = "---"
	trimmed := bytes.TrimLeft(src, " \t\r\n")
	if !bytes.HasPrefix(trimmed, []byte(fence)) {
		return nil, errNoFrontmatter
	}
	rest := trimmed[len(fence):]
	idx := bytes.Index(rest, []byte("\n"+fence))
	if idx < 0 {
		return nil, errNoFrontmatter
	}
	return rest[:idx], nil
}

// ParseFrontmatter strictly decodes the frontmatter, rejecting unknown or
// wrongly-nested keys so that structural mistakes surface as errors instead of
// being silently dropped.
func ParseFrontmatter(block []byte) (Frontmatter, error) {
	var fm Frontmatter
	dec := yaml.NewDecoder(bytes.NewReader(block))
	dec.KnownFields(true)
	if err := dec.Decode(&fm); err != nil {
		return Frontmatter{}, fmt.Errorf("invalid frontmatter: %w", err)
	}
	return fm, nil
}
