package config

import (
	"context"
	"fmt"
	"time"

	"github.com/go-playground/validator/v10"
	"github.com/sethvargo/go-envconfig"
)

// Config объединяет все необходимые секции конфигурации для вашего проекта.
type Config struct {
	Server   ServerConfig   `env:",prefix=SERVER_"`
	DB       DBConfig       `env:",prefix=DATABASE_"`
	LLM      LLMConfig      `env:",prefix=LLM_"`
	Kafka    KafkaConfig    `env:",prefix=KAFKA_"`
	OTEL     OTelConfig     `env:",prefix=OTEL_"`
	Telegram TelegramConfig `env:",prefix=TELEGRAM_"`
}

// ServerConfig содержит параметры HTTP-сервера.
type ServerConfig struct {
	AppName string `env:"APP_NAME,default=ProductAssistant" validate:"required"`
	Port    string `env:"PORT,default=8080" validate:"required"`
	Secret  string `env:"SECRET,default=secret" validate:"required"`
}

type DBConfig struct {
	Hostname string `env:"HOSTNAME, default=localhost"`
	Port     int    `env:"PORT, default=5435"`
	User     string `env:"USER, default=postgres"`
	Password string `env:"PASSWORD, default=secret"`
	Dbname   string `env:"DBNAME, default=products_db"`
}

func (c *DBConfig) ConnectionString() string {
	return fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable", c.Hostname, c.User, c.Password, c.Dbname, c.Port)
}

// LLMConfig содержит настройки для работы с LLM (модель, API-ключ, endpoint).
type LLMConfig struct {
	Embedder  string `env:"EMBEDDER,default=bge-m3" validate:"required"`
	ModelName string `env:"MODEL_NAME,default=mistral-large-latest" validate:"required"`
	APIKey    string `env:"API_KEY,default=ZdDk5S3QxaEytpf9DWXM2nEb6GVHuF9y" validate:"required"`
	Endpoint  string `env:"ENDPOINT, default=http://localhost:11434" validate:"required,url"`
}

// KafkaConfig содержит общие настройки для Kafka.
type KafkaConfig struct {
	BootstrapServers []string       `env:"BOOTSTRAP_SERVERS, default=localhost:9092" validate:"required,dive,hostname_port"`
	SSLCertPath      string         `env:"SSL_CERT_PATH"`
	SSLKeyPath       string         `env:"SSL_KEY_PATH"`
	SSLCaCert        string         `env:"SSL_CA_CERT"`
	VerifyCert       bool           `env:"VERIFY_CERT,default=false"`
	Producer         ProducerConfig `env:",prefix=PRODUCER_"`
	Consumer         ConsumerConfig `env:",prefix=CONSUMER_"`
}

// ProducerConfig содержит настройки для продюсера Kafka.
type ProducerConfig struct {
	Topic                  string `env:"TOPIC, default=price_changes" validate:"required"`
	Async                  bool   `env:"ASYNC, default=false"`
	AllowAutoTopicCreation bool   `env:"ALLOW_AUTO_TOPIC_CREATION, default=true"`
}

// ConsumerConfig содержит настройки для консьюмера Kafka.
type ConsumerConfig struct {
	Topic   string `env:"TOPIC, default=price_changes" validate:"required"`
	GroupID string `env:"GROUP_ID, default=notifications_group" validate:"required"`
}

// OTelConfig содержит настройки для OpenTelemetry.
type OTelConfig struct {
	OTLP OTLPConfig `env:",prefix=OTLP_"`
}

// OTLPConfig задаёт параметры приёма трейсов.
type OTLPConfig struct {
	Insecure bool          `env:"INSECURE,default=true"`
	Endpoint string        `env:"ENDPOINT,default=localhost:4317" validate:"required,url"`
	Timeout  time.Duration `env:"TIMEOUT,default=10s"`
	HTTP     bool          `env:"HTTP,default=false"`
	Retry    RetryConfig   `env:",prefix=RETRY_"`
}

// RetryConfig содержит настройки повторных попыток для OTLP.
type RetryConfig struct {
	Enabled         bool          `env:"ENABLED,default=true"`
	InitialInterval time.Duration `env:"INITIAL_INTERVAL,default=5s"`
	MaxInterval     time.Duration `env:"MAX_INTERVAL,default=30s"`
	MaxElapsedTime  time.Duration `env:"MAX_ELAPSED_TIME,default=1m"`
}

type TelegramConfig struct {
	BotToken  string `env:"BOT_TOKEN,default=7665408380:AAFKbUgbdQb3iX6X-29H3spv4KGG1FXs_IM" validate:"required"`
	JWTSecret string `env:"JWT_SECRET,default=secret" validate:"required"`
}

// NewConfig загружает конфигурацию из переменных окружения и проводит валидацию.
func NewConfig(ctx context.Context) (*Config, error) {
	var cfg Config
	if err := envconfig.Process(ctx, &cfg); err != nil {
		return nil, fmt.Errorf("failed to process env config: %w", err)
	}
	if err := cfg.Validate(); err != nil {
		return nil, fmt.Errorf("config validation error: %w", err)
	}
	return &cfg, nil
}

// Validate проверяет корректность настроек с использованием пакета validator.
func (c *Config) Validate() error {
	validate := validator.New()
	return validate.Struct(c)
}