package config

import (
	"flag"
	"fmt"

	"github.com/fsnotify/fsnotify"
	"github.com/pingcap/dbaas/billing2/billing_errors"
	"github.com/pingcap/log"
	"github.com/spf13/viper"
	ov "github.com/tidbcloud/config-service/oneconfig/viper"
	"go.uber.org/zap"
)

const (
	// Deployment Project
	Project = "project"

	// Default Unit Category
	DefaultUnitCategory       = "default-unit-category"
	DefaultLabelValueCategory = "default-label-value-category"

	// BillingServerPort is the billing server port
	BillingServerPort = "billing-server-port"
	// MySQLHost is the mysql host key
	MySQLHost = "mysql-host"
	// MySQLUser is the mysql user key
	MySQLUser = "mysql-user"
	//billing database
	Database = "database"
	// MySQLPassword is the mysql password key
	MySQLPassword = "mysql-password"
	// MySQLPasswordFile is the file contains the mysql password
	MySQLPasswordFile = "mysql-password-file"
	// MySQLPasswordUseFile identify if we get mysql password in file
	MySQLPasswordUseFile = "mysql-password-use-file"
	// MYSQLPort is the mysql port key
	MYSQLPort = "mysql-port"

	// Validate units exists in package create and update
	PackageUnitsValidate = "package-units-validate"

	DBaaSCentralEnable = "dbaas-central-enable"
	// DBaaSCentralHost is the rpc call addr: host with port
	DBaaSCentralHost = "dbaas-central-host"
	// DBaaSCentralScheme  is the rpc scheme
	DBaaSCentralScheme = "dbaas-central-scheme"
	// DBaaSCentralAuth0Domain  is the auth0 domain
	DBaaSCentralAuth0Domain = "dbaas-central-auth0-domain"
	// DBaaSCentralClientID  is the auth0 client id
	DBaaSCentralAuth0ClientID = "dbaas-central-auth0-client-id"
	// DBaaSCentralClientSecret is the auth0 client secret
	DBaaSCentralAuth0ClientSecret = "dbaas-central-auth0-client-secret" //nolint:gosec
	// DBaaSCentralAudience  is the auth0 client audience
	DBaaSCentralAuth0Audience = "dbaas-central-auth0-client-audience"

	// InvoiceWorkerCheckInterval specify the invoice work interval, default is 5m
	InvoiceWorkerCheckInterval = "invoice-worker-check-interval"
	// InvoiceDay is the day of month to send invoice
	InvoiceDay = "invoice-day"

	// EnableInvoiceWorker identify if invoice worker is enabled
	EnableInvoiceWorker = "enable-invoice-worker"
	// EnableAuth identify if auth is enabled
	EnableAuth = "enable-auth"

	// stripe-payment-enable
	StripePaymentEnable = "stripe-payment-enable"
	// StripeSecretKey is the stripe secret key
	StripeSecretKey = "stripe-secret-key"
	// StripePublicKey is the stripe pubic key
	StripePublicKey = "stripe-public-key"

	EnableSyncPayableWorker   = "enable-sync-payable-worker"
	SyncPayableWorkerInterval = "sync-payable-worker-interval"
	CalculateCacheInterval    = "calculate-cache-interval"
	RemoveUnusedCostsInterval = "remove-unused-costs-interval"
	MergeSmallCostsInterval   = "merge-small-costs-interval"

	RemoveUnusedCostsDays = "remove-unused-costs-days"
	MergeSmallCostsDays   = "merge-small-costs-days"

	// aws-payment-enable
	AWSPaymentEnable = "aws-payment-enable"
	// Aws MarketPlace Region
	AwsMarketplaceRegion = "aws-marketplace-region"
	// Aws MarketPlace ProductCode
	AWSProductCode = "aws-marketplace-productcode"
	AWSRole        = "aws-role"
	AWSProductUnit = "aws-product-unit"
	// 1000 means 0.001
	AWSProudctUnitPriceFactor = "aws-product-unit-price-factor"

	CostSummaryGroupLabelList = "cost-summary-group-label-list"

	GlobalPricePackage = "global-price-package"

	// Gcp MarketPlace
	GCPPaymentEnable          = "gcp-payment-enable"
	GCPProcurementBaseUrl     = "gcp-procurement-base-url"
	GCPProductCode            = "gcp-marketplace-productcode"
	GCPProductUnit            = "gcp-product-unit"
	GCPMarketPlaceProject     = "gcp-marketplace-project"
	GCPProudctUnitPriceFactor = "gcp-product-unit-price-factor"
	GCPMarketPlaceSA          = "gcp-marketplace-sa"

	BillingCostsPrecisionDigits = "billing-costs-precision-digits"

	KeeyShowingCategory = "keey-showing-category"
	RedisHost           = "redis-host"

	EnableCache = "enable-cache"

	CDNFileContentType = "cdn-file-content-type"
)

var (
	configPath = flag.String("conf", "/etc/billing/", "billing system configuration file")
)

func LoadRemote() error {
	remote := fmt.Sprintf("%s/oneconfig-billing/config.yaml", viper.GetString(Project))
	log.Info("Read From Remote", zap.String("remote", remote))
	err := viper.AddRemoteProvider(ov.Provider, ov.Endpoint, remote)
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	err = viper.WatchRemoteConfig()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	err = viper.GetViper().WatchRemoteConfigOnChannel()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}
	return nil
}

// Init init the viper
func Init() error {
	err := InitLocal()
	if err != nil {
		return err
	}
	err = LoadRemote()
	if err != nil {
		log.Warn("load remote config failed, just ignore it in persnonal project", zap.Error(err))
	}

	viper.OnConfigChange(func(e fsnotify.Event) {
		log.Info("Config file changed:", zap.String("path", e.Name))
	})
	return nil
}

func InitLocal() error {
	flag.Parse()
	viper.SetDefault(DefaultUnitCategory, "Default")
	viper.SetDefault(DefaultLabelValueCategory, "default")
	viper.SetDefault(MySQLHost, "localhost")
	viper.SetDefault(MySQLUser, "root")
	viper.SetDefault(Database, "billing2")
	viper.SetDefault(MySQLPasswordUseFile, false)
	viper.SetDefault(DBaaSCentralEnable, true)
	viper.SetDefault(MYSQLPort, uint16(3306))
	viper.SetDefault(DBaaSCentralEnable, true)
	viper.SetDefault(DBaaSCentralScheme, "http")
	viper.SetDefault(DBaaSCentralHost, "central-http:11000")
	viper.SetDefault(InvoiceDay, 3)
	viper.SetDefault(StripePaymentEnable, false)
	viper.SetDefault(AWSProudctUnitPriceFactor, 1000)
	viper.SetDefault(AWSPaymentEnable, false)
	viper.SetDefault(InvoiceWorkerCheckInterval, "5m")
	viper.SetDefault(SyncPayableWorkerInterval, "5m")
	viper.SetDefault(CalculateCacheInterval, "30m")
	viper.SetDefault(PackageUnitsValidate, true)
	viper.SetDefault(EnableInvoiceWorker, true)
	viper.SetDefault(EnableSyncPayableWorker, true)
	viper.SetDefault(BillingServerPort, 18888)
	viper.SetDefault(CostSummaryGroupLabelList, "project")
	viper.SetDefault(GCPPaymentEnable, false)
	viper.SetDefault(GCPProudctUnitPriceFactor, 1000)
	viper.SetDefault(GCPProcurementBaseUrl, "https://cloudcommerceprocurement.googleapis.com/")
	viper.SetDefault(RedisHost, "redis-cache:6379")
	viper.SetDefault(RemoveUnusedCostsInterval, "12h")
	viper.SetDefault(MergeSmallCostsInterval, "12h")
	viper.SetDefault(RemoveUnusedCostsDays, 7)
	viper.SetDefault(MergeSmallCostsDays, 2)
	viper.SetDefault(EnableCache, true)
	viper.SetDefault(CDNFileContentType, "application/octet-stream")

	viper.SetDefault(BillingCostsPrecisionDigits, 2)

	viper.AddConfigPath(*configPath)
	viper.AutomaticEnv()
	err := viper.ReadInConfig()
	if err != nil {
		return billing_errors.NewSystemError(err)
	}

	viper.WatchConfig()
	return nil
}
