package config

import (
	"os"
	"time"

	"code.justin.tv/creator-collab/log/errors"
	"code.justin.tv/eventbus/client/publisher"
	"code.justin.tv/live/autohost/internal/localdynamo"
)

const (
	// Service id from the catalog https://servicecatalog.internal.justin.tv/services/161
	AutohostTwitchServiceID = "161"

	// EnvDev is the "development environment".  A service is running in the development environment
	// when it is running locally on someone's laptop.
	EnvDev = "development"
	// EnvCI is the "continuous integration environment".  This means the service is running in Jenkins.
	EnvCI = "ci"
	// EnvStaging is the staging environment.
	EnvStaging = "staging"
	// EnvProduction is the production environment.
	EnvProduction = "production"
)

type Config struct {
	EnableCloudWatchMetrics      bool
	Environment                  string
	RunningInEC2                 bool
	SetListSNSARNV2              string
	EventBusQueueURL             string
	PDMSRoleArn                  string
	PDMSLambdaArn                string
	Redis                        Redis
	S2S2ServiceName              string
	UseDevelopmentLogger         bool
	EventBusPublisherEnvironment publisher.Environment

	ClientURL        ClientURL
	SecretManagerARN SecretManagerARN
	DynamoDB         DynamoDB
	Memcached        Memcached
	TwitchRecs       TwitchRecs
	RateLimiting     RateLimiting
}

type ClientURL struct {
	Clue     string
	Hallpass string
	Liveline string
	Pubsub   string
	Users    string
}

type SecretManagerARN struct {
	RollbarToken string
}

type DynamoDB struct {
	HostTableName       string
	SettingsTableName   string
	LocalDynamo         bool
	LocalDynamoEndpoint string
}

type Memcached struct {
	// Determines if the client is using a memcached server that supports Auto Discovery. This
	// is only supported with AWS Elasticache. When true, the ConfigurationEndpoint is expected
	// to be the auto discovery configuration endpoint. If false, configuration endpoint
	// should be the server url hosting Memcached.
	UseAutoDiscovery bool

	// The complete url of the cache endpoint. Should include the port number. If UseAutoDiscovery
	// is true, this should be the main configuration endpoint for the memcached cluster.
	//
	// Examples
	// When UseAutoDiscovery false: 127.0.0.1:11211
	// When UseAutoDiscovery true: amazon.url.cfg.usw2.cache.amazonaws.com:11211
	ConfigurationEndpoint string

	// Poll interval for auto discovery. If no value is set, the default value is used.
	PollInterval time.Duration

	// Specifies the read/write timeout for the memcached connection. If none provided or
	// set to zero, the client will use the default value
	Timeout time.Duration

	// This specifies the max idle connections available for the memcached client. The memcached
	// client will attempt to grab an idle connection before creating a new connection to the server.
	MaxIdleConnections int

	// Determines the desired number of idle connections to create at start
	PrewarmConnections int
}

type Redis struct {
	// Address should be of the form host:port
	Address string
	Cluster bool
}

type RateLimiting struct {
	MaxHostOperations  int
	HostWindowDuration time.Duration

	MaxUnhostOperations  int
	UnhostWindowDuration time.Duration
}

type TwitchRecs struct {
	// The endpoint url for the TwitchRecs service
	EndpointURL string

	// For local development only. Used to connect to a socks proxy to allow local access
	// to the TwitchRecs service
	ProxyURL string

	// The assigned product id for the specified environment used to make requests with TwitchRecs
	ProductID string
}

func GetConfig() (*Config, error) {
	env, set := os.LookupEnv("ENVIRONMENT")
	if !set {
		return nil, errors.New("Environment variable named \"ENVIRONMENT\" was not set")
	}

	switch env {
	case EnvDev:
		return &DevelopmentConfig, nil
	case EnvCI:
		return &CIConfig, nil
	case EnvStaging:
		return &StagingConfig, nil
	case EnvProduction:
		return &ProductionConfig, nil
	}

	return nil, errors.New("could not config for given environment", errors.Fields{
		"ENVIRONMENT": env,
	})
}

var DevelopmentConfig = Config{
	EnableCloudWatchMetrics:      false,
	Environment:                  EnvDev,
	RunningInEC2:                 false,
	SetListSNSARNV2:              "",
	EventBusPublisherEnvironment: publisher.EnvDevelopment,
	EventBusQueueURL:             "https://sqs.us-west-2.amazonaws.com/038504843107/eventbus-queue-beta",
	UseDevelopmentLogger:         true,
	S2S2ServiceName:              "autohost-staging",
	ClientURL: ClientURL{
		Clue:     "https://staging.clue.twitch.a2z.com",
		Hallpass: "http://staging.hallpass.cb.twitch.a2z.com",
		Liveline: "http://vpce-0bca21115628b1354-bsespffb.vpce-svc-0e4e8f90d47bca00d.us-west-2.vpce.amazonaws.com",
		Pubsub:   "https://darklaunch.pubsub-broker.twitch.a2z.com",
		Users:    "https://dev.users-service.twitch.a2z.com",
	},
	DynamoDB: DynamoDB{
		HostTableName:       localdynamo.TableHost,
		SettingsTableName:   localdynamo.TableAutohostSettings,
		LocalDynamo:         true,
		LocalDynamoEndpoint: "http://localhost:8401",
	},
	Memcached: Memcached{
		UseAutoDiscovery:      false,
		ConfigurationEndpoint: "localhost:11211",
		MaxIdleConnections:    1000,
		Timeout:               350 * time.Millisecond,
		PrewarmConnections:    150,
	},
	RateLimiting: RateLimiting{
		MaxHostOperations:    100,
		HostWindowDuration:   time.Second,
		MaxUnhostOperations:  100,
		UnhostWindowDuration: time.Second,
	},
	Redis: Redis{
		Address: "localhost:8400",
		// Use non-clustered Redis because it's difficult to configure Redis
		// to run as a cluster when it is running in a Docker container.
		Cluster: false,
	},
	SecretManagerARN: SecretManagerARN{
		RollbarToken: "",
	},
	PDMSRoleArn:   "arn:aws:iam::895799599216:role/PDMSLambda-CallerRole-18451FI19HSXT",
	PDMSLambdaArn: "arn:aws:lambda:us-west-2:895799599216:function:PDMSLambda-LambdaFunction-IT8I1PE1YR81:live",
	TwitchRecs: TwitchRecs{
		EndpointURL: "https://us-west-2.beta.twitchrecs.s.twitch.a2z.com",
		ProxyURL:    "socks5:127.0.0.1:1080",
		ProductID:   "product-autohost-test",
	},
}

var CIConfig = Config{
	Environment:                  EnvCI,
	SetListSNSARNV2:              "",
	EventBusPublisherEnvironment: publisher.EnvStaging,
	EventBusQueueURL:             "https://sqs.us-west-2.amazonaws.com/038504843107/eventbus-queue-beta",
	UseDevelopmentLogger:         true,
	S2S2ServiceName:              "autohost-staging",
	ClientURL: ClientURL{
		Clue:     "https://staging.clue.twitch.a2z.com",
		Hallpass: "http://staging.hallpass.cb.twitch.a2z.com",
		Liveline: "http://vpce-0bca21115628b1354-bsespffb.vpce-svc-0e4e8f90d47bca00d.us-west-2.vpce.amazonaws.com",
		Pubsub:   "https://darklaunch.pubsub-broker.twitch.a2z.com",
		Users:    "https://dev.users-service.twitch.a2z.com",
	},
	DynamoDB: DynamoDB{
		HostTableName:       localdynamo.TableHost,
		SettingsTableName:   localdynamo.TableAutohostSettings,
		LocalDynamo:         true,
		LocalDynamoEndpoint: "http://db:8000",
	},
	Memcached: Memcached{
		UseAutoDiscovery:      false,
		ConfigurationEndpoint: "memcached:11211",
		MaxIdleConnections:    1000,
		Timeout:               350 * time.Millisecond,
		PrewarmConnections:    150,
	},
	RateLimiting: RateLimiting{
		MaxHostOperations:    100,
		HostWindowDuration:   time.Second,
		MaxUnhostOperations:  100,
		UnhostWindowDuration: time.Second,
	},
	Redis: Redis{
		Address: "redis:6379",
		// Use non-clustered Redis because it's difficult to configure Redis
		// to run as a cluster when it is running in a Docker container.
		Cluster: false,
	},
	SecretManagerARN: SecretManagerARN{
		RollbarToken: "",
	},
	PDMSRoleArn:   "arn:aws:iam::895799599216:role/PDMSLambda-CallerRole-18451FI19HSXT",
	PDMSLambdaArn: "arn:aws:lambda:us-west-2:895799599216:function:PDMSLambda-LambdaFunction-IT8I1PE1YR81:live",
	TwitchRecs: TwitchRecs{
		EndpointURL: "https://us-west-2.beta.twitchrecs.s.twitch.a2z.com",
		ProductID:   "product-autohost-test",
	},
}

var StagingConfig = Config{
	EnableCloudWatchMetrics:      true,
	Environment:                  EnvStaging,
	RunningInEC2:                 true,
	EventBusPublisherEnvironment: publisher.EnvStaging,
	SetListSNSARNV2:              "arn:aws:sns:us-west-2:038504843107:autohost_staging_list_updates",
	EventBusQueueURL:             "https://sqs.us-west-2.amazonaws.com/038504843107/eventbus-queue-beta",
	S2S2ServiceName:              "autohost-staging",
	ClientURL: ClientURL{
		Clue:     "https://staging.clue.twitch.a2z.com",
		Hallpass: "http://staging.hallpass.cb.twitch.a2z.com",
		Liveline: "http://vpce-0bca21115628b1354-bsespffb.vpce-svc-0e4e8f90d47bca00d.us-west-2.vpce.amazonaws.com",
		Pubsub:   "https://darklaunch.pubsub-broker.twitch.a2z.com",
		Users:    "https://dev.users-service.twitch.a2z.com",
	},
	DynamoDB: DynamoDB{
		HostTableName:       "Host-staging",
		SettingsTableName:   "staging-settings",
		LocalDynamo:         false,
		LocalDynamoEndpoint: "",
	},
	Memcached: Memcached{
		UseAutoDiscovery:      true,
		ConfigurationEndpoint: "aut-el-l88ehc0gq9qo.nctct5.cfg.usw2.cache.amazonaws.com:11211",
		PollInterval:          1 * time.Minute,
		MaxIdleConnections:    1000,
		Timeout:               350 * time.Millisecond,
		PrewarmConnections:    150,
	},
	RateLimiting: RateLimiting{
		MaxHostOperations:    100,
		HostWindowDuration:   time.Second,
		MaxUnhostOperations:  100,
		UnhostWindowDuration: time.Second,
	},
	Redis: Redis{
		Address: "raids.nctct5.clustercfg.usw2.cache.amazonaws.com:6379",
		Cluster: true,
	},
	SecretManagerARN: SecretManagerARN{
		RollbarToken: "arn:aws:secretsmanager:us-west-2:038504843107:secret:Autohost-Staging-Rollbar-fajsIp",
	},
	PDMSRoleArn:   "arn:aws:iam::895799599216:role/PDMSLambda-CallerRole-18451FI19HSXT",
	PDMSLambdaArn: "arn:aws:lambda:us-west-2:895799599216:function:PDMSLambda-LambdaFunction-IT8I1PE1YR81:live",
	TwitchRecs: TwitchRecs{
		EndpointURL: "https://us-west-2.beta.twitchrecs.s.twitch.a2z.com",
		ProductID:   "product-autohost-test",
	},
}

var ProductionConfig = Config{
	EnableCloudWatchMetrics:      true,
	Environment:                  EnvProduction,
	RunningInEC2:                 true,
	EventBusPublisherEnvironment: publisher.EnvProduction,
	SetListSNSARNV2:              "arn:aws:sns:us-west-2:447680546588:autohost_production_list_updates",
	EventBusQueueURL:             "https://sqs.us-west-2.amazonaws.com/447680546588/eventbus-queue-prod",
	S2S2ServiceName:              "autohost-prod",
	ClientURL: ClientURL{
		Clue:     "https://prod.clue.twitch.a2z.com",
		Hallpass: "http://prod.hallpass.cb.twitch.a2z.com",
		Liveline: "http://vpce-043f71368e31b65ed-4bza3e8m.vpce-svc-09e5395f949c1bf56.us-west-2.vpce.amazonaws.com",
		Pubsub:   "https://prod.pubsub-broker.twitch.a2z.com",
		Users:    "https://prod.users-service.twitch.a2z.com",
	},
	DynamoDB: DynamoDB{
		HostTableName:       "Host-production",
		SettingsTableName:   "production-settings",
		LocalDynamo:         false,
		LocalDynamoEndpoint: "",
	},
	Memcached: Memcached{
		UseAutoDiscovery:      true,
		ConfigurationEndpoint: "aut-el-1aw863r4xzf0j.usx3jl.cfg.usw2.cache.amazonaws.com:11211",
		PollInterval:          1 * time.Minute,
		MaxIdleConnections:    6000,
		Timeout:               350 * time.Millisecond,
		PrewarmConnections:    150,
	},
	RateLimiting: RateLimiting{
		// Chosen to be close to the limit that's implemented for the /host slash command, but
		// high enough that legit users shouldn't encounter it.
		MaxHostOperations:  10,
		HostWindowDuration: 30 * time.Minute,

		// Chosen arbitrarily to balance between always allowing a user to unhost themselves, and
		// to protect our systems from being overwhelmed by a runaway script.
		MaxUnhostOperations:  5,
		UnhostWindowDuration: 5 * time.Second,
	},
	Redis: Redis{
		Address: "raids.usx3jl.clustercfg.usw2.cache.amazonaws.com:6379",
		Cluster: true,
	},
	SecretManagerARN: SecretManagerARN{
		RollbarToken: "arn:aws:secretsmanager:us-west-2:447680546588:secret:Autohost-Production-Rollbar-1WhkMv",
	},
	PDMSRoleArn:   "arn:aws:iam::125704643346:role/PDMSLambda-CallerRole-13IIND444YKVR",
	PDMSLambdaArn: "arn:aws:lambda:us-west-2:125704643346:function:PDMSLambda-LambdaFunction-11LXHJVSNJJPY:live",
	TwitchRecs: TwitchRecs{
		EndpointURL: "https://us-west-2.prod.twitchrecs.s.twitch.a2z.com",
		ProductID:   "product-autohost",
	},
}
