package config

import (
	"time"

	"github.com/joho/godotenv"
	"github.com/kelseyhightower/envconfig"

	customErrors "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/helper/errors"
)

type Service struct {
	appPort                     uint16
	appStaticPath               string
	appTemplatesPath            string
	corsAllowOrigins            string
	corsAllowMethods            string
	dbDriver                    string
	dbHost                      string
	dbPort                      uint16
	dbName                      string
	dbUser                      string
	dbPassword                  string
	dbMaxOpenConns              uint16
	dbMaxIdleConns              uint16
	dbMaxOpenConnLifetime       time.Duration
	dbMaxIdleConnLifetime       time.Duration
	cacheDefaultDuration        time.Duration
	smtpHost                    string
	smtpPort                    uint16
	smtpUser                    string
	smtpPassword                string
	jwtSecretKey                string
	jwtLifeTime                 time.Duration
	jwtCookie                   string
	basicAuthUser               string
	basicAuthPassword           string
	staticVersion               uint16
	loggerStdoutEnabled         bool
	loggerStdoutLevel           string
	loggerFileEnabled           bool
	loggerFileLevel             string
	loggerFilePath              string
	loggerEmailEnabled          bool
	loggerEmailLevel            string
	loggerEmailSubject          string
	loggerEmailRecipient        string
	loginRateLimiterMaxRequests uint16
	loginRateLimiterExpiration  time.Duration
}

func Init() (*Service, error) {
	s := struct {
		AppPort                     uint16        `envconfig:"APP_PORT"`
		AppStaticPath               string        `envconfig:"APP_STATIC_PATH"`
		AppTemplatesPath            string        `envconfig:"APP_TEMPLATES_PATH"`
		CorsAllowOriginsOrigins     string        `envconfig:"CORS_ALLOW_ORIGIN"`
		CorsAllowMethods            string        `envconfig:"CORS_ALLOW_METHODS"`
		DBDriver                    string        `envconfig:"DB_DRIVER"`
		DBHost                      string        `envconfig:"DB_HOST"`
		DBPort                      uint16        `envconfig:"DB_PORT"`
		DBName                      string        `envconfig:"DB_NAME"`
		DBUser                      string        `envconfig:"DB_USER"`
		DBPassword                  string        `envconfig:"DB_PASSWORD"`
		DBMaxOpenConns              uint16        `envconfig:"DB_MAX_OPEN_CONNS"`
		DBMaxIdleConns              uint16        `envconfig:"DB_MAX_IDLE_CONNS"`
		DBMaxOpenConnLifetime       time.Duration `envconfig:"DB_MAX_OPEN_CONN_LIFETIME"`
		DBMaxIdleConnLifetime       time.Duration `envconfig:"DB_MAX_IDLE_CONN_LIFETIME"`
		CacheDefaultDuration        time.Duration `envconfig:"CACHE_DEFAULT_EXPIRATION"`
		SMTPHost                    string        `envconfig:"SMTP_HOST"`
		SMTPPort                    uint16        `envconfig:"SMTP_PORT"`
		SMTPUser                    string        `envconfig:"SMTP_USER"`
		SMTPPassword                string        `envconfig:"SMTP_PASSWORD"`
		JWTSecretKey                string        `envconfig:"JWT_SECRET_KEY"`
		JWTLifeTime                 time.Duration `envconfig:"JWT_LIFETIME"`
		JWTCookie                   string        `envconfig:"JWT_COOKIE"`
		BasicAuthUser               string        `envconfig:"BASIC_AUTH_USER"`
		BasicAuthPassword           string        `envconfig:"BASIC_AUTH_PASSWORD"`
		StaticVersion               uint16        `envconfig:"STATIC_VERSION"`
		LoggerStdoutEnabled         bool          `envconfig:"LOGGER_STDOUT_ENABLED"`
		LoggerStdoutLevel           string        `envconfig:"LOGGER_STDOUT_LEVEL"`
		LoggerFileEnabled           bool          `envconfig:"LOGGER_FILE_ENABLED"`
		LoggerFileLevel             string        `envconfig:"LOGGER_FILE_LEVEL"`
		LoggerFilePath              string        `envconfig:"LOGGER_FILE_PATH"`
		LoggerEmailEnabled          bool          `envconfig:"LOGGER_EMAIL_ENABLED"`
		LoggerEmailLevel            string        `envconfig:"LOGGER_EMAIL_LEVEL"`
		LoggerEmailSubject          string        `envconfig:"LOGGER_EMAIL_SUBJECT"`
		LoggerEmailRecipient        string        `envconfig:"LOGGER_EMAIL_RECIPIENT"`
		LoginRateLimiterMaxRequests uint16        `envconfig:"LOGIN_RATE_LIMITER_MAX_REQUESTS"`
		LoginRateLimiterExpiration  time.Duration `envconfig:"LOGIN_RATE_LIMITER_EXPIRATION"`
	}{}

	_ = godotenv.Overload()

	if err := envconfig.Process("", &s); err != nil {
		return nil, customErrors.Wrap(err, "process config")
	}

	return &Service{
		appPort:                     s.AppPort,
		appStaticPath:               s.AppStaticPath,
		appTemplatesPath:            s.AppTemplatesPath,
		corsAllowOrigins:            s.CorsAllowOriginsOrigins,
		corsAllowMethods:            s.CorsAllowMethods,
		dbDriver:                    s.DBDriver,
		dbHost:                      s.DBHost,
		dbPort:                      s.DBPort,
		dbName:                      s.DBName,
		dbUser:                      s.DBUser,
		dbPassword:                  s.DBPassword,
		dbMaxOpenConns:              s.DBMaxOpenConns,
		dbMaxIdleConns:              s.DBMaxIdleConns,
		dbMaxOpenConnLifetime:       s.DBMaxOpenConnLifetime,
		dbMaxIdleConnLifetime:       s.DBMaxIdleConnLifetime,
		cacheDefaultDuration:        s.CacheDefaultDuration,
		smtpHost:                    s.SMTPHost,
		smtpPort:                    s.SMTPPort,
		smtpUser:                    s.SMTPUser,
		smtpPassword:                s.SMTPPassword,
		jwtSecretKey:                s.JWTSecretKey,
		jwtLifeTime:                 s.JWTLifeTime,
		jwtCookie:                   s.JWTCookie,
		basicAuthUser:               s.BasicAuthUser,
		basicAuthPassword:           s.BasicAuthPassword,
		staticVersion:               s.StaticVersion,
		loggerStdoutEnabled:         s.LoggerStdoutEnabled,
		loggerStdoutLevel:           s.LoggerStdoutLevel,
		loggerFileEnabled:           s.LoggerFileEnabled,
		loggerFileLevel:             s.LoggerFileLevel,
		loggerFilePath:              s.LoggerFilePath,
		loggerEmailEnabled:          s.LoggerEmailEnabled,
		loggerEmailLevel:            s.LoggerEmailLevel,
		loggerEmailSubject:          s.LoggerEmailSubject,
		loggerEmailRecipient:        s.LoggerEmailRecipient,
		loginRateLimiterMaxRequests: s.LoginRateLimiterMaxRequests,
		loginRateLimiterExpiration:  s.LoginRateLimiterExpiration,
	}, nil
}

func (s Service) AppPort() uint16 {
	return s.appPort
}

func (s Service) AppStaticPath() string {
	return s.appStaticPath
}

func (s Service) AppTemplatesPath() string {
	return s.appTemplatesPath
}

func (s Service) CORSAllowOrigins() string {
	return s.corsAllowOrigins
}

func (s Service) CORSAllowMethods() string {
	return s.corsAllowMethods
}

func (s Service) DBDriver() string {
	return s.dbDriver
}

func (s Service) DBHost() string {
	return s.dbHost
}

func (s Service) DBPort() uint16 {
	return s.dbPort
}

func (s Service) DBName() string {
	return s.dbName
}

func (s Service) DBUser() string {
	return s.dbUser
}

func (s Service) DBPassword() string {
	return s.dbPassword
}

func (s Service) DBMaxOpenConns() uint16 {
	return s.dbMaxOpenConns
}

func (s Service) DBMaxIdleConns() uint16 {
	return s.dbMaxIdleConns
}

func (s Service) DBMaxOpenConnLifetime() time.Duration {
	return s.dbMaxOpenConnLifetime
}

func (s Service) DBMaxIdleConnLifetime() time.Duration {
	return s.dbMaxIdleConnLifetime
}

func (s Service) CacheDefaultDuration() time.Duration {
	return s.cacheDefaultDuration
}

func (s Service) SMTPHost() string {
	return s.smtpHost
}

func (s Service) SMTPPort() uint16 {
	return s.smtpPort
}

func (s Service) SMTPUser() string {
	return s.smtpUser
}

func (s Service) SMTPPassword() string {
	return s.smtpPassword
}

func (s Service) JWTSecretKey() string {
	return s.jwtSecretKey
}

func (s Service) JWTLifeTime() time.Duration {
	return s.jwtLifeTime
}

func (s Service) JWTCookie() string {
	return s.jwtCookie
}

func (s Service) BasicAuthUser() string {
	return s.basicAuthUser
}

func (s Service) BasicAuthPassword() string {
	return s.basicAuthPassword
}

func (s Service) StaticVersion() uint16 {
	return s.staticVersion
}

func (s Service) LoggerStdoutEnabled() bool {
	return s.loggerStdoutEnabled
}

func (s Service) LoggerStdoutLevel() string {
	return s.loggerStdoutLevel
}

func (s Service) LoggerFileEnabled() bool {
	return s.loggerFileEnabled
}

func (s Service) LoggerFileLevel() string {
	return s.loggerFileLevel
}

func (s Service) LoggerFilePath() string {
	return s.loggerFilePath
}

func (s Service) LoggerEmailEnabled() bool {
	return s.loggerEmailEnabled
}

func (s Service) LoggerEmailLevel() string {
	return s.loggerEmailLevel
}

func (s Service) LoggerEmailSubject() string {
	return s.loggerEmailSubject
}

func (s Service) LoggerEmailRecipient() string {
	return s.loggerEmailRecipient
}

func (s Service) LoginRateLimiterMaxRequests() uint16 {
	return s.loginRateLimiterMaxRequests
}

func (s Service) LoginRateLimiterExpiration() time.Duration {
	return s.loginRateLimiterExpiration
}
