// Package agent реализует агент сбора метрик для pulse-lets-go.
// Агент работает на каждой PBX-ноде (FreeSWITCH или Asterisk),
// собирает метрики и публикует их в NATS каждые 5 секунд.
//
// Поддерживаемые типы PBX:
//   - "freeswitch" — сбор через ESL (Event Socket Library)
//   - "asterisk"   — сбор через AMI (Asterisk Manager Interface)
//
// Пример agent.json:
//
//	{
//	  "node_id": "uc06",
//	  "type": "asterisk",
//	  "nats_url": "nats://balancer.lan:4222",
//	  "sip_gateway": "sip:uc-pbx.lan:5060",
//	  "interval_sec": 5,
//	  "max_calls": 150,
//	  "ami": { "host": "127.0.0.1", "port": 6154, "username": "admin", "password": "changeme" }
//	}
package agent

import (
	"encoding/json"
	"fmt"
	"os"
)

// Config — конфигурация агента (agent.json).
type Config struct {
	NodeID         string `json:"node_id"`  // уникальный ID ноды (uc06, ses-sip)
	Type           string `json:"type"`     // "freeswitch" или "asterisk"
	NatsURL        string `json:"nats_url"` // NATS URL
	NatsUser       string `json:"nats_user,omitempty"`
	NatsPassword   string `json:"nats_password,omitempty"`
	IntervalSec    int    `json:"interval_sec"`     // интервал сбора (default: 5)
	MaxCalls       int    `json:"max_calls"`        // ёмкость ноды (default: 250)
	SIPGateway     string `json:"sip_gateway"`      // SIP-адрес для auto-транка
	SIPGatewayAuto bool   `json:"sip_gateway_auto"` // авто-определить из PBX
	FailureWindow  int    `json:"failure_window"`   // окно для call_failure_rate (default: 1000)
	ESL            ESLCfg `json:"esl,omitempty"`
	AMI            AMICfg `json:"ami,omitempty"`
}

// ESLCfg — настройки подключения к FreeSWITCH ESL.
type ESLCfg struct {
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Password string `json:"password"`
}

// AMICfg — настройки подключения к Asterisk AMI.
type AMICfg struct {
	Host     string `json:"host"`
	Port     int    `json:"port"`
	Username string `json:"username"`
	Password string `json:"password"`
}

// LoadConfig загружает конфигурацию агента из JSON-файла.
func LoadConfig(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("чтение %s: %w", path, err)
	}

	var cfg Config
	if err := json.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("парсинг %s: %w", path, err)
	}

	// Defaults
	if cfg.IntervalSec <= 0 {
		cfg.IntervalSec = 5
	}
	if cfg.MaxCalls <= 0 {
		cfg.MaxCalls = 250
	}
	if cfg.FailureWindow <= 0 {
		cfg.FailureWindow = 1000
	}
	if cfg.ESL.Port == 0 {
		cfg.ESL.Port = 8021
	}
	if cfg.AMI.Port == 0 {
		cfg.AMI.Port = 5038
	}

	return &cfg, nil
}

// Validate проверяет корректность конфигурации.
func (c *Config) Validate() error {
	if c.NodeID == "" {
		return fmt.Errorf("node_id обязателен")
	}
	if c.NatsURL == "" {
		return fmt.Errorf("nats_url обязателен")
	}
	switch c.Type {
	case "freeswitch":
		if c.ESL.Host == "" {
			return fmt.Errorf("esl.host обязателен для type=freeswitch")
		}
	case "asterisk":
		if c.AMI.Host == "" {
			return fmt.Errorf("ami.host обязателен для type=asterisk")
		}
	default:
		return fmt.Errorf("type должен быть freeswitch или asterisk, получен: %s", c.Type)
	}
	return nil
}

// GetSIPGateway возвращает SIP-адрес для авто-транка.
// Если SIPGatewayAuto = true — вернётся "" (collector определит сам).
func (c *Config) GetSIPGateway(autoDetected string) string {
	if c.SIPGateway != "" {
		return c.SIPGateway
	}
	if c.SIPGatewayAuto {
		return autoDetected
	}
	return ""
}
