package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"gitea.pena/PenaSide/common/encrypt"
	"gitea.pena/PenaSide/common/validate"
	"gitea.pena/PenaSide/customer/internal/models"
	"github.com/stretchr/testify/assert"
	"os"
	"testing"
)

func TestValidateTG(t *testing.T) {
	err := validateTG("7127966184:AAG1steOCH4wDvHRe9QcsXJPS4dWRyRYsqg", -1002177203276, -1002177203276)
	assert.NoError(t, err)
}

func TestValidateMail(t *testing.T) {
	err := validateMail(models.MailClientCfg{
		ApiURL:      "https://api.smtp.bz/v1/smtp/send",
		Sender:      "noreply@mailing.pena.digital",
		ApiKey:      "P0YsjUB137upXrr1NiJefHmXVKW1hmBWlpev",
		MailAddress: "sells@pena.digital",
	})
	assert.NoError(t, err)
}

func TestValidateURLs(t *testing.T) {
	urls := []string{
		"http://10.8.0.6:59300",
		"http://10.8.0.6:59303",
		"http://10.8.0.6:3131",
		"10.8.0.6:9001",
		"10.8.0.6:9085",
		"http://10.8.0.6:7036",
		"http://10.6.0.17",
		"https://api.smtp.bz/v1/smtp/send",
		"10.8.0.6:59665",
		"https://sadmin.pena",
		"10.8.0.15:7113",
	}
	err := validateURLs(urls)
	assert.NoError(t, err)
}

func TestValidateKafka(t *testing.T) {
	err := validateKafka([]string{"localhost:9092"}, "test-topic")
	assert.NoError(t, err)
}

func TestValidateEncryptKeys(t *testing.T) {
	priveKey, pubKey, err := generateRSAKeys(2048)
	assert.NoError(t, err)
	err = validate.ValidateEncryptKeys(&encrypt.Encrypt{
		PubKey:  pubKey,
		PrivKey: priveKey,
	})
	assert.NoError(t, err)
}

func generateRSAKeys(bitSize int) (privateKey string, publicKey string, err error) {
	privKey, err := rsa.GenerateKey(rand.Reader, bitSize)
	if err != nil {
		return "", "", err
	}

	privKeyPEM := pem.EncodeToMemory(&pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(privKey),
	})

	pubKeyBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey)
	if err != nil {
		return "", "", err
	}
	pubKeyPEM := pem.EncodeToMemory(&pem.Block{
		Type:  "RSA PUBLIC KEY",
		Bytes: pubKeyBytes,
	})

	return string(privKeyPEM), string(pubKeyPEM), nil
}

func TestLoadConfig(t *testing.T) {
	envVars := map[string]string{
		"JWT_ISSUER":                       "pena-auth-service",
		"JWT_AUDIENCE":                     "pena",
		"JWT_PUBLIC_KEY":                   "-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm69\n80fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6B\ndA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y\n+3GyaOY536H47qyXAgMBAAE=\n-----END PUBLIC KEY-----",
		"CLIENT_HTTP_URL":                  "0.0.0.0:8080",
		"ADMIN_HTTP_URL":                   "0.0.0.0:8081",
		"GRPC_URL":                         "0.0.0.0:9001",
		"GRPC_DOMAIN":                      "customer-service:9000",
		"MONGO_URL":                        "mongodb://test:test@localhost:27020/",
		"MONGO_DB_NAME":                    "admin",
		"KAFKA_BROKERS":                    "localhost:9092",
		"KAFKA_TOPIC_TARIFF":               "test-topic",
		"AUTH_MICROSERVICE_URL":            "http://localhost:8000/user",
		"HUBADMIN_MICROSERVICE_URL":        "http://localhost:8001/tariff",
		"CURRENCY_MICROSERVICE_URL":        "http://cbrfworker-service:8000/change",
		"DISCOUNT_MICROSERVICE_GRPC_URL":   "localhost:9040",
		"PAYMENT_MICROSERVICE_GRPC_URL":    "treasurer-service:9085",
		"VERIFICATION_MICROSERVICE_URL":    "http://10.8.0.8:7035/verification",
		"TEMPLATEGEN_MICROSERVICE_URL":     "10.6.0.17",
		"CODEWORD_MICROSERVICE_GRPC_URL":   "http://localhost:8000/user",
		"TRASH_LOG_HOST":                   "localhost:7113",
		"API_URL":                          "https://api.smtp.bz/v1/smtp/send",
		"MAIL_SENDER":                      "noreply@mailing.pena.digital",
		"MAIL_API_KEY":                     "P0YsjUB137upXrr1NiJefHmXVKW1hmBWlpev",
		"MAIL_ADDRESS":                     "mail@mail.com",
		"TELEGRAM_TOKEN":                   "7127966184:AAG1steOCH4wDvHRe9QcsXJPS4dWRyRYsqg",
		"TELEGRAM_NOTIFICATION_CHANNEL_ID": "-1002177203276",
		"TELEGRAM_RS_PAY_CHANNEL_ID":       "-1002177203276",
		"ADMIN_FRONT_URL":                  "https://admin-front.ru",
	}

	priveKey, pubKey, err := generateRSAKeys(2048)
	assert.NoError(t, err)

	envVars["ENCRYPT_PUBLIC_KEY"] = pubKey
	envVars["ENCRYPT_PRIVATE_KEY"] = priveKey

	for key, value := range envVars {
		os.Setenv(key, value)
	}

	cfg, err := loadConfig()
	assert.Nil(t, err)

	err = validateNotEmpty(cfg)
	if err != nil {
		assert.NoError(t, err)
	}

	urls := []string{
		cfg.AuthMicroserviceURL,
		cfg.HubadminMicroserviceURL,
		cfg.CurrencyMicroserviceURL,
		cfg.DiscountMicroserviceGRPC,
		cfg.CodewordMicroserviceGRPC,
		cfg.PaymentMicroserviceGRPC,
		cfg.VerificationMicroservice,
		cfg.TemplategenMicroserviceURL,
		cfg.TrashLogHost,
		cfg.AdminURL,
		cfg.ExternalCfg.MailClientCfg.ApiURL,
	}
	if err = validateURLs(urls); err != nil {
		assert.NoError(t, err)
	}

	// todo validate jwt

	if err = validateKafka(cfg.KafkaBrokers, cfg.KafkaTopicTariff); err != nil {
		assert.NoError(t, err)
	}

	if err = validateMail(cfg.ExternalCfg.MailClientCfg); err != nil {
		assert.NoError(t, err)
	}

	if err = validate.ValidateEncryptKeys(&cfg.ExternalCfg.EncryptCommon); err != nil {
		assert.NoError(t, err)
	}

	if err = validateTG(cfg.NotificationBotToken, cfg.NotificationRsPayChannel, cfg.NotificationChannel); err != nil {
		assert.NoError(t, err)
	}

	if err = validate.ValidateMongo(cfg.ExternalCfg.Database); err != nil {
		assert.NoError(t, err)
	}

}
