package config

import (
	"github.com/UpmeshLTD/urus-aio/infrastructure/broker"
	"github.com/UpmeshLTD/urus-aio/infrastructure/config"
	"github.com/UpmeshLTD/urus-aio/infrastructure/enums"
	"github.com/spf13/viper"
)

type configImpl struct {
	viper        *viper.Viper
	systemConfig *SystemConfig
}

type SystemConfig struct {
	App                 App                 `mapstructure:",squash"`
	Database            Database            `mapstructure:",squash"`
	GRPC                GRPC                `mapstructure:",squash"`
	HTTP                HTTP                `mapstructure:",squash"`
	Auth                Auth                `mapstructure:",squash"`
	Aws                 Aws                 `mapstructure:",squash"`
	EzShip              EzShip              `mapstructure:",squash"`
	ShipmentProvider    ShipmentProvider    `mapstructure:",squash"`
	MessageBrokerConfig MessageBrokerConfig `mapstructure:",squash"`
	Swagger             Swagger             `mapstructure:",squash"`
}

//go:generate mockery --name=Config --case=snake
type Config interface {
	GetAppConfig() App
	GetDatabaseConfig() Database
	GetGRPCConfig() GRPC
	GetHTTPConfig() HTTP
	GetAuthConfig() Auth
	GetShipmentProviderConfig() ShipmentProvider
	GetAwsConfig() Aws
	GetMessageBrokerConfig() broker.MessageBrokerConfig
	GetSwaggerConfig() Swagger
	IsDevelopment() bool
}

func NewConfig() (Config, error) {
	cfg := &configImpl{
		viper: viper.New(),
	}
	systemCfg := &SystemConfig{}
	cfg.setDefaultConfig()
	res, err := config.LoadConfig(cfg.viper, systemCfg)
	if err != nil {
		return nil, err
	}
	return &configImpl{
		systemConfig: res.(*SystemConfig),
	}, nil
}

func (c *configImpl) setDefaultConfig() {
	c.setDefaultAppConfig()
	c.setDefaultDatabaseConfig()
	c.setDefaultGRPCConfig()
	c.setDefaultHTTPConfig()
	c.setDefaultAuthConfig()
	c.setDefaultAwsConfig()
}

func (c *configImpl) IsDevelopment() bool {
	return c.GetAppConfig().Environment == enums.EnvDevelopment
}
