package config

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

	"gopkg.in/yaml.v3"
)

// AutomationToolsFileName is the Phase 5 config file basename.
const AutomationToolsFileName = "automation-tools.yaml"

// AutomationToolsDocument is the on-disk shape.
type AutomationToolsDocument struct {
	AutomationTools []AutomationToolConfig `yaml:"automation_tools"`
}

// AutomationToolConfig is one tool entry. API tokens live in the secrets
// store under `automation_tool:<id>:api_token`, never in YAML.
type AutomationToolConfig struct {
	ID                  string         `yaml:"id"`
	Name                string         `yaml:"name"`
	Type                string         `yaml:"type"` // "autobrr" (Phase 5); "tqm" / "crossseed" later
	BaseURL             string         `yaml:"base_url"`
	Enabled             *bool          `yaml:"enabled,omitempty"`
	PollIntervalSeconds int            `yaml:"poll_interval_seconds"`
	WebhookEndpointID   string         `yaml:"webhook_endpoint_id,omitempty"`
	Config              map[string]any `yaml:"config,omitempty"`
}

// IsEnabled returns true if Enabled is omitted or true.
func (t AutomationToolConfig) IsEnabled() bool {
	if t.Enabled == nil {
		return true
	}
	return *t.Enabled
}

// LoadAutomationToolsFromDir reads the file from dir; absent file is OK.
func LoadAutomationToolsFromDir(dir string) (*AutomationToolsDocument, error) {
	path := filepath.Join(dir, AutomationToolsFileName)
	data, err := os.ReadFile(path)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return &AutomationToolsDocument{}, nil
		}
		return nil, fmt.Errorf("config: read %s: %w", path, err)
	}
	return LoadAutomationToolsFromBytes(data)
}

// LoadAutomationToolsFromBytes parses + validates.
func LoadAutomationToolsFromBytes(data []byte) (*AutomationToolsDocument, error) {
	var doc AutomationToolsDocument
	if err := yaml.Unmarshal(data, &doc); err != nil {
		return nil, fmt.Errorf("config: automation-tools.yaml parse: %w", err)
	}
	if err := doc.Validate(); err != nil {
		return nil, err
	}
	for i := range doc.AutomationTools {
		t := &doc.AutomationTools[i]
		if t.PollIntervalSeconds == 0 {
			t.PollIntervalSeconds = 60
		}
	}
	return &doc, nil
}

// Validate enforces uniqueness and required fields.
func (d *AutomationToolsDocument) Validate() error {
	seen := map[string]struct{}{}
	for i, t := range d.AutomationTools {
		if t.ID == "" {
			return fmt.Errorf("config: automation_tools[%d]: id required", i)
		}
		if t.Type == "" {
			return fmt.Errorf("config: automation_tools[%d] (%s): type required", i, t.ID)
		}
		if t.BaseURL == "" {
			return fmt.Errorf("config: automation_tools[%d] (%s): base_url required", i, t.ID)
		}
		if t.PollIntervalSeconds < 0 {
			return fmt.Errorf("config: automation_tools[%d] (%s): poll_interval_seconds must be non-negative", i, t.ID)
		}
		if _, dup := seen[t.ID]; dup {
			return fmt.Errorf("config: duplicate automation_tool id %q", t.ID)
		}
		seen[t.ID] = struct{}{}
	}
	return nil
}
