package config

import (
	"Yimaru-Backend/internal/domain"
	customlogger "Yimaru-Backend/internal/logger"
	"errors"
	"log/slog"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/joho/godotenv"
)

var (
	ErrInvalidDbUrl            = errors.New("db url is invalid")
	ErrInvalidPort             = errors.New("port number is invalid")
	ErrRefreshExpiry           = errors.New("refresh token expiry is invalid")
	ErrAccessExpiry            = errors.New("access token expiry is invalid")
	ErrInvalidJwtKey           = errors.New("jwt key is invalid")
	ErrLogLevel                = errors.New("log level not set")
	ErrInvalidLevel            = errors.New("invalid log level")
	ErrInvalidEnv              = errors.New("env not set or invalid")
	ErrInvalidReportExportPath = errors.New("report export path is invalid")
	ErrInvalidSMSAPIKey        = errors.New("SMS API key is invalid")

	ErrMissingResendApiKey            = errors.New("missing Resend Api key")
	ErrMissingResendSenderEmail       = errors.New("missing Resend sender name")
	ErrMissingTwilioAccountSid        = errors.New("missing twilio account sid")
	ErrMissingTwilioAuthToken         = errors.New("missing twilio auth token")
	ErrMissingTwilioSenderPhoneNumber = errors.New("missing twilio sender phone number")
)

type AFROSMSConfig struct {
	AfroSMSSenderName   string `mapstructure:"afrom_sms_sender_name"`
	AfroSMSIdentifierID string `mapstructure:"afro_sms_identifier_id"`
	AfroSMSAPIKey       string `mapstructure:"afro_sms_api_key"`
	AfroSMSBaseURL      string `mapstructure:"afro_sms_base_url"`
}

type ARIFPAYConfig struct {
	APIKey  string `mapstructure:"ARIFPAY_API_KEY"`
	BaseURL string `mapstructure:"ARIFPAY_BASE_URL"`

	// Default URLs
	CancelUrl    string `mapstructure:"cancelUrl"`
	SuccessUrl   string `mapstructure:"successUrl"`
	ErrorUrl     string `mapstructure:"errorUrl"`
	B2CNotifyUrl string `mapstructure:"notifyUrl"`
	C2BNotifyUrl string `mapstructure:"notifyUrl"`

	// Default Payment Configs
	PaymentMethods           []string `mapstructure:"paymentMethods"`
	ExpireDate               string   `mapstructure:"expireDate"`
	ItemName                 string   `mapstructure:"name"`
	Quantity                 int      `mapstructure:"quantity"`
	Description              string   `mapstructure:"description"`
	BeneficiaryAccountNumber string   `mapstructure:"accountNumber"`
	Bank                     string   `mapstructure:"bank"`
	Lang                     string   `mapstructure:"amount"`
}

type SANTIMPAYConfig struct {
	SecretKey  string `mapstructure:"secret_key"`
	MerchantID string `mapstructure:"merchantId"`
	BaseURL    string `mapstructure:"base_url"`
	NotifyURL  string `mapstructure:"notifyUrl"`
	CancelUrl  string `mapstructure:"cancelUrl"`
	SuccessUrl string `mapstructure:"successUrl"`
}

type TELEBIRRConfig struct {
	TelebirrFabricAppID  string `mapstructure:"fabric_app_id"`
	TelebirrAppSecret    string `mapstructure:"appSecret"`
	TelebirrBaseURL      string `mapstructure:"base_url"`
	TelebirrMerchantCode string `mapstructure:"merchant_code"`
	TelebirrCallbackURL  string `mapstructure:"callback_url"`
}

type VimeoConfig struct {
	AccessToken string `mapstructure:"vimeo_access_token"`
	Enabled     bool   `mapstructure:"vimeo_enabled"`
}

type CloudConvertConfig struct {
	APIKey  string `mapstructure:"cloudconvert_api_key"`
	Enabled bool   `mapstructure:"cloudconvert_enabled"`
}

type Config struct {
	GoogleOAuthClientID            string
	GoogleOAuthClientSecret        string
	GoogleOAuthRedirectURL         string
	AFROSMSConfig                  AFROSMSConfig `mapstructure:"afro_sms_config"`
	Vimeo                          VimeoConfig          `mapstructure:"vimeo_config"`
	CloudConvert                   CloudConvertConfig   `mapstructure:"cloudconvert_config"`
	APP_VERSION                    string
	FIXER_API_KEY                  string
	FIXER_BASE_URL                 string
	BASE_CURRENCY                  domain.IntCurrency
	Port                           int
	Service                        string
	DbUrl                          string
	RefreshExpiry                  int
	AccessExpiry                   int
	JwtKey                         string
	LogLevel                       slog.Level
	Env                            string
	ReportExportPath               string `mapstructure:"REPORT_EXPORT_PATH"`
	AFRO_SMS_API_KEY               string
	AFRO_SMS_SENDER_NAME           string
	AFRO_SMS_RECEIVER_PHONE_NUMBER string
	ADRO_SMS_HOST_URL              string
	CHAPA_WEBHOOK_SECRET           string
	CHAPA_TRANSFER_TYPE            string
	CHAPA_PAYMENT_TYPE             string
	CHAPA_SECRET_KEY               string
	CHAPA_PUBLIC_KEY               string
	CHAPA_BASE_URL                 string
	CHAPA_ENCRYPTION_KEY           string
	CHAPA_CALLBACK_URL             string
	CHAPA_RETURN_URL               string
	CHAPA_RECEIPT_URL              string
	ARIFPAY                        ARIFPAYConfig   `mapstructure:"arifpay_config"`
	SANTIMPAY                      SANTIMPAYConfig `mapstructure:"santimpay_config"`
	TELEBIRR                       TELEBIRRConfig  `mapstructure:"telebirr_config"`
	ResendApiKey                   string
	ResendSenderEmail              string
	TwilioAccountSid               string
	TwilioAuthToken                string
	TwilioSenderPhoneNumber        string
	RedisAddr                      string
	KafkaBrokers                   []string
	FCMServiceAccountKey           string
}

func NewConfig() (*Config, error) {
	config := &Config{}
	if err := config.loadEnv(); err != nil {
		return nil, err
	}
	return config, nil
}

func (c *Config) loadEnv() error {
	err := godotenv.Load()
	if err != nil && !os.IsNotExist(err) {
		return errors.New("failed to load env file: " + err.Error())
	}

	env := os.Getenv("ENV")
	if env == "" {
		return ErrInvalidEnv
	}
	c.Env = env

	c.GoogleOAuthClientID = os.Getenv("GOOGLE_OAUTH_CLIENT_ID")
	c.GoogleOAuthClientSecret = os.Getenv("GOOGLE_OAUTH_CLIENT_SECRET")
	c.GoogleOAuthRedirectURL = os.Getenv("GOOGLE_OAUTH_REDIRECT_URL")

	c.APP_VERSION = os.Getenv("APP_VERSION")

	c.ReportExportPath = os.Getenv("REPORT_EXPORT_PATH")

	if c.ReportExportPath == "" {
		return ErrInvalidReportExportPath
	}
	c.RedisAddr = os.Getenv("REDIS_ADDR")
	c.KafkaBrokers = strings.Split(os.Getenv("KAFKA_BROKERS"), ",")

	c.CHAPA_TRANSFER_TYPE = os.Getenv("CHAPA_TRANSFER_TYPE")
	c.CHAPA_PAYMENT_TYPE = os.Getenv("CHAPA_PAYMENT_TYPE")

	c.FIXER_API_KEY = os.Getenv("FIXER_API_KEY")
	c.BASE_CURRENCY = domain.IntCurrency(os.Getenv("BASE_CURRENCY"))
	c.FIXER_BASE_URL = os.Getenv("FIXER_BASE_URL")

	portStr := os.Getenv("PORT")
	if portStr == "" {
		return ErrInvalidPort
	}
	port, err := strconv.Atoi(portStr)
	if err != nil || port < 1 || port > 65535 {
		return ErrInvalidPort
	}
	c.Port = port

	dbUrl := os.Getenv("DB_URL")
	if dbUrl == "" {
		return ErrInvalidDbUrl
	}
	c.DbUrl = dbUrl

	refreshExpiryStr := os.Getenv("REFRESH_EXPIRY")
	if refreshExpiryStr == "" {
		return ErrRefreshExpiry
	}
	refreshExpiry, err := strconv.Atoi(refreshExpiryStr)
	if err != nil || refreshExpiry <= 0 {
		return ErrRefreshExpiry
	}
	c.RefreshExpiry = refreshExpiry

	jwtKey := os.Getenv("JWT_KEY")
	if jwtKey == "" {
		return ErrInvalidJwtKey
	}
	c.JwtKey = jwtKey

	accessExpiryStr := os.Getenv("ACCESS_EXPIRY")
	if accessExpiryStr == "" {
		return ErrAccessExpiry
	}
	accessExpiry, err := strconv.Atoi(accessExpiryStr)
	if err != nil || accessExpiry <= 0 {
		return ErrAccessExpiry
	}
	c.AccessExpiry = accessExpiry

	logLevel := os.Getenv("LOG_LEVEL")
	if logLevel == "" {
		return ErrLogLevel
	}

	lvl, ok := customlogger.LogLevels[logLevel]
	if !ok {
		return ErrInvalidLevel
	}

	//Afro SMS
	c.AFROSMSConfig.AfroSMSAPIKey = os.Getenv("AFRO_SMS_API_KEY")
	c.AFROSMSConfig.AfroSMSIdentifierID = os.Getenv("AFRO_SMS_IDENTIFIER_ID")
	c.AFROSMSConfig.AfroSMSBaseURL = os.Getenv("AFRO_SMS_BASE_URL")
	c.AFROSMSConfig.AfroSMSSenderName = os.Getenv("AFRO_SMS_SENDER_NAME")

	//Telebirr
	c.TELEBIRR.TelebirrBaseURL = os.Getenv("TELEBIRR_BASE_URL")
	c.TELEBIRR.TelebirrAppSecret = os.Getenv("TELEBIRR_APP_SECRET")
	c.TELEBIRR.TelebirrAppSecret = os.Getenv("TELEBIRR_FABRIC_APP_ID")
	c.TELEBIRR.TelebirrMerchantCode = os.Getenv("TELEBIRR_MERCHANT_CODE")
	c.TELEBIRR.TelebirrCallbackURL = os.Getenv("TELEBIRR_CALLBACK_URL")

	//Chapa
	c.CHAPA_WEBHOOK_SECRET = os.Getenv("CHAPA_WEBHOOK_SECRET")
	c.CHAPA_SECRET_KEY = os.Getenv("CHAPA_SECRET_KEY")
	c.CHAPA_PUBLIC_KEY = os.Getenv("CHAPA_PUBLIC_KEY")
	c.CHAPA_ENCRYPTION_KEY = os.Getenv("CHAPA_ENCRYPTION_KEY")
	c.CHAPA_BASE_URL = os.Getenv("CHAPA_BASE_URL")
	c.CHAPA_RECEIPT_URL = os.Getenv("CHAPA_RECEIPT_URL")
	if c.CHAPA_BASE_URL == "" {
		c.CHAPA_BASE_URL = "https://api.chapa.co/v1"
	}
	c.CHAPA_CALLBACK_URL = os.Getenv("CHAPA_CALLBACK_URL")
	c.CHAPA_RETURN_URL = os.Getenv("CHAPA_RETURN_URL")

	c.ARIFPAY.APIKey = os.Getenv("ARIFPAY_API_KEY")
	c.ARIFPAY.CancelUrl = os.Getenv("ARIFPAY_CANCEL_URL")
	c.ARIFPAY.ErrorUrl = os.Getenv("ARIFPAY_ERROR_URL")
	c.ARIFPAY.C2BNotifyUrl = os.Getenv("ARIFPAY_C2B_NOTIFY_URL")
	c.ARIFPAY.B2CNotifyUrl = os.Getenv("ARIFPAY_B2C_NOTIFY_URL")
	c.ARIFPAY.SuccessUrl = os.Getenv("ARIFPAY_SUCCESS_URL")
	c.ARIFPAY.BaseURL = os.Getenv("ARIFPAY_BASE_URL")
	c.ARIFPAY.Bank = os.Getenv("ARIFPAY_BANK")
	c.ARIFPAY.BeneficiaryAccountNumber = os.Getenv("ARIFPAY_BENEFICIARY_ACCOUNT_NUMBER")
	c.ARIFPAY.Description = os.Getenv("ARIFPAY_DESCRIPTION")
	c.ARIFPAY.ExpireDate = time.Now().Add(time.Hour * 3).Format("2006-01-02")
	c.ARIFPAY.ItemName = os.Getenv("ARIFPAY_ITEM_NAME")
	c.ARIFPAY.Lang = "EN"
	c.ARIFPAY.Quantity = 1
	c.ARIFPAY.PaymentMethods = []string{"TELEBIRR", "AWAASH", "AWAASH_WALLET", "PSS", "CBE", "AMOLE", "BOA", "KACHA", "TELEBIRR", "HELLOCASH", "MPESSA"}

	c.SANTIMPAY.SecretKey = os.Getenv("SANTIMPAY_SECRET_KEY")
	c.SANTIMPAY.MerchantID = os.Getenv("SANTIMPAY_MERCHANT_ID")
	c.SANTIMPAY.BaseURL = os.Getenv("SANTIMPAY_BASE_URL")
	c.SANTIMPAY.NotifyURL = os.Getenv("SANTIMPAY_NOTIFY_URL")
	c.SANTIMPAY.CancelUrl = os.Getenv("SANTIMPAY_CANCEL_URL")

	// //Alea Play
	// aleaEnabled := os.Getenv("ALEA_ENABLED")
	// if aleaEnabled == "" {
	// 	aleaEnabled = "false" // Default disabled
	// }

	// if enabled, err := strconv.ParseBool(aleaEnabled); err != nil {
	// 	return fmt.Errorf("invalid ALEA_ENABLED value: %w", err)
	// } else {
	// 	c.AleaPlay.Enabled = enabled
	// }

	// c.AleaPlay.BaseURL = os.Getenv("ALEA_BASE_URL")
	// if c.AleaPlay.BaseURL == "" && c.AleaPlay.Enabled {
	// 	return errors.New("ALEA_BASE_URL is required when Alea is enabled")
	// }

	// c.AleaPlay.OperatorID = os.Getenv("ALEA_OPERATOR_ID")
	// if c.AleaPlay.OperatorID == "" && c.AleaPlay.Enabled {
	// 	return errors.New("ALEA_OPERATOR_ID is required when Alea is enabled")
	// }

	// c.AleaPlay.SecretKey = os.Getenv("ALEA_SECRET_KEY")
	// if c.AleaPlay.SecretKey == "" && c.AleaPlay.Enabled {
	// 	return errors.New("ALEA_SECRET_KEY is required when Alea is enabled")
	// }

	// c.AleaPlay.GameListURL = os.Getenv("ALEA_GAME_LIST_URL")
	// c.AleaPlay.DefaultCurrency = os.Getenv("ALEA_DEFAULT_CURRENCY")
	// if c.AleaPlay.DefaultCurrency == "" {
	// 	c.AleaPlay.DefaultCurrency = "USD"
	// }

	// sessionTimeoutStr := os.Getenv("ALEA_SESSION_TIMEOUT")
	// if sessionTimeoutStr != "" {
	// 	timeout, err := strconv.Atoi(sessionTimeoutStr)
	// 	if err == nil {
	// 		c.AleaPlay.SessionTimeout = timeout
	// 	}
	// }

	// //Veli Games
	// veliEnabled := os.Getenv("VELI_ENABLED")
	// if veliEnabled == "" {
	// 	veliEnabled = "true" // Default to disabled if not specified
	// }
	// veliOperatorID := os.Getenv("VELI_OPERATOR_ID")
	// veliBrandID := os.Getenv("VELI_BRAND_ID")
	// c.VeliGames.OperatorID = os.Getenv("VELI_OPERATOR_ID")
	// c.VeliGames.BrandID = os.Getenv("VELI_BRAND_ID")

	// if enabled, err := strconv.ParseBool(veliEnabled); err != nil {
	// 	return fmt.Errorf("invalid VELI_ENABLED value: %w", err)
	// } else {
	// 	c.VeliGames.Enabled = enabled
	// }

	// // apiURL := os.Getenv("VELI_BASE_URL")
	// // if apiURL == "" {
	// // 	apiURL = "https://api.velitech.games" // Default production URL
	// // }
	// c.VeliGames.BaseURL = os.Getenv("VELI_BASE_URL")

	// operatorKey := os.Getenv("VELI_OPERATOR_KEY")
	// if operatorKey == "" && c.VeliGames.Enabled {
	// 	return ErrInvalidVeliOperatorKey
	// }
	// c.VeliGames.OperatorKey = operatorKey

	// secretKey := os.Getenv("VELI_SECRET_KEY")
	// if secretKey == "" && c.VeliGames.Enabled {
	// 	return ErrInvalidVeliSecretKey
	// }
	// c.VeliGames.SecretKey = secretKey
	// // c.VeliGames.GameIDs.Aviator = os.Getenv("VELI_GAME_ID_AVIATOR")

	// defaultCurrency := os.Getenv("VELI_DEFAULT_CURRENCY")
	// if defaultCurrency == "" {
	// 	defaultCurrency = "USD" // Default currency
	// }
	// c.VeliGames.DefaultCurrency = defaultCurrency

	c.LogLevel = lvl

	c.AFRO_SMS_API_KEY = os.Getenv("AFRO_SMS_API_KEY")
	if c.AFRO_SMS_API_KEY == "" {
		return ErrInvalidSMSAPIKey
	}

	c.AFRO_SMS_SENDER_NAME = os.Getenv("AFRO_SMS_SENDER_NAME")
	if c.AFRO_SMS_SENDER_NAME == "" {
		c.AFRO_SMS_SENDER_NAME = "Yimaru"
	}

	c.AFRO_SMS_RECEIVER_PHONE_NUMBER = os.Getenv("AFRO_SMS_RECEIVER_PHONE_NUMBER")

	c.ADRO_SMS_HOST_URL = os.Getenv("ADRO_SMS_HOST_URL")
	if c.ADRO_SMS_HOST_URL == "" {
		c.ADRO_SMS_HOST_URL = "https://api.afromessage.com"
	}

	//Atlas
	// c.Atlas.BaseURL = os.Getenv("ATLAS_BASE_URL")
	// c.Atlas.CasinoID = os.Getenv("ATLAS_CASINO_ID")
	// c.Atlas.OperatorID = os.Getenv("ATLAS_OPERATOR_ID")
	// c.Atlas.PartnerID = os.Getenv("ATLAS_PARTNER_ID")
	// c.Atlas.SecretKey = os.Getenv("ATLAS_SECRET_KEY")

	// popOKClientID := os.Getenv("POPOK_CLIENT_ID")

	// // popOKPlatform := os.Getenv("POPOK_PLATFORM")

	// if popOKClientID == "" {
	// 	return ErrInvalidPopOKClientID
	// }

	// popOKSecretKey := os.Getenv("POPOK_SECRET_KEY")
	// if popOKSecretKey == "" {
	// 	return ErrInvalidPopOKSecretKey
	// }

	// popOKBaseURL := os.Getenv("POPOK_BASE_URL")
	// if popOKBaseURL == "" {
	// 	return ErrInvalidPopOKBaseURL
	// }

	// popOKCallbackURL := os.Getenv("POPOK_CALLBACK_URL")
	// if popOKCallbackURL == "" {
	// 	return ErrInvalidPopOKCallbackURL
	// }

	// c.PopOK = domain.PopOKConfig{
	// 	ClientID:    popOKClientID,
	// 	SecretKey:   popOKSecretKey,
	// 	BaseURL:     popOKBaseURL,
	// 	CallbackURL: popOKCallbackURL,
	// 	Platform:    popOKPlatform,
	// }

	// AtlasBaseUrl := os.Getenv("ATLAS_BASE_URL")
	// if AtlasBaseUrl == "" {
	// 	return ErrInvalidAtlasBaseUrl
	// }
	// AtlasSecretKey := os.Getenv("ATLAS_SECRET_KEY")
	// if AtlasSecretKey == "" {
	// 	return ErrInvalidAtlasSecretKey
	// }
	// AtlasBrandID := os.Getenv("ATLAS_BRAND_ID")
	// if AtlasBrandID == "" {
	// 	return ErrInvalidAtlasBrandID
	// }
	// AtlasPartnerID := os.Getenv("ATLAS_PARTNER_ID")
	// if AtlasPartnerID == "" {
	// 	return ErrInvalidAtlasPartnerID
	// }
	// AtlasOperatorID := os.Getenv("ATLAS_OPERATOR_ID")
	// if AtlasOperatorID == "" {
	// 	return ErrInvalidAtlasOperatorID
	// }

	// c.Atlas = AtlasConfig{
	// 	BaseURL:    AtlasBaseUrl,
	// 	SecretKey:  AtlasSecretKey,
	// 	CasinoID:   AtlasBrandID,
	// 	PartnerID:  AtlasPartnerID,
	// 	OperatorID: AtlasOperatorID,
	// }

	// betToken := os.Getenv("BET365_TOKEN")
	// if betToken == "" {
	// 	return ErrMissingBetToken
	// }
	// c.Bet365Token = betToken

	resendApiKey := os.Getenv("RESEND_API_KEY")
	if resendApiKey == "" {
		return ErrMissingResendApiKey
	}
	c.ResendApiKey = resendApiKey

	resendSenderEmail := os.Getenv("RESEND_SENDER_EMAIL")
	if resendSenderEmail == "" {
		return ErrMissingResendSenderEmail
	}
	c.ResendSenderEmail = resendSenderEmail

	twilioAccountSid := os.Getenv("TWILIO_ACCOUNT_SID")
	if twilioAccountSid == "" {
		return ErrMissingTwilioAccountSid
	}
	c.TwilioAccountSid = twilioAccountSid

	twilioAuthToken := os.Getenv("TWILIO_AUTH_TOKEN")
	if twilioAuthToken == "" {
		return ErrMissingTwilioAuthToken
	}
	c.TwilioAuthToken = twilioAuthToken

	twilioSenderPhoneNumber := os.Getenv("TWILIO_SENDER_PHONE_NUMBER")
	if twilioSenderPhoneNumber == "" {
		return ErrMissingTwilioSenderPhoneNumber
	}
	c.TwilioSenderPhoneNumber = twilioSenderPhoneNumber

	c.FCMServiceAccountKey = os.Getenv("FCM_SERVICE_ACCOUNT_KEY")

	// Vimeo configuration
	vimeoEnabled := os.Getenv("VIMEO_ENABLED")
	if vimeoEnabled == "true" || vimeoEnabled == "1" {
		c.Vimeo.Enabled = true
	}
	c.Vimeo.AccessToken = os.Getenv("VIMEO_ACCESS_TOKEN")

	// CloudConvert configuration
	cloudConvertEnabled := os.Getenv("CLOUDCONVERT_ENABLED")
	if cloudConvertEnabled == "true" || cloudConvertEnabled == "1" {
		c.CloudConvert.Enabled = true
	}
	c.CloudConvert.APIKey = os.Getenv("CLOUDCONVERT_API_KEY")

	return nil
}

type ChapaConfig struct {
	ChapaPaymentType  string `mapstructure:"chapa_payment_type"`
	ChapaTransferType string `mapstructure:"chapa_transfer_type"`
}
