package main

import (
	"context"
	"fmt"
	"gitea.pena/PenaSide/common/validate"
	"gitea.pena/PenaSide/customer/internal/models"
	"github.com/caarlos0/env/v8"
	"github.com/gofiber/fiber/v2"
	"github.com/twmb/franz-go/pkg/kgo"
	"log"
	"time"
)

func main() {
	config, err := loadConfig()
	if err != nil {
		log.Fatalf("error loading config: %v", err)
	}

	err = validateNotEmpty(config)
	if err != nil {
		log.Fatalf("error validating config: %v", err)
	}

	urls := []string{
		config.AuthMicroserviceURL,
		config.HubadminMicroserviceURL,
		config.CurrencyMicroserviceURL,
		config.DiscountMicroserviceGRPC,
		config.CodewordMicroserviceGRPC,
		config.PaymentMicroserviceGRPC,
		config.VerificationMicroservice,
		config.TemplategenMicroserviceURL,
		config.TrashLogHost,
		config.AdminURL,
		config.ExternalCfg.MailClientCfg.ApiURL,
	}
	if err = validateURLs(urls); err != nil {
		log.Fatalf("error validating urls: %v", err)
	}

	// todo validate jwt

	if err = validateKafka(config.KafkaBrokers, config.KafkaTopicTariff); err != nil {
		log.Fatalf("error validating kafka: %v", err)
	}

	if err = validateMail(config.ExternalCfg.MailClientCfg); err != nil {
		log.Fatalf("error validating smtp: %v", err)
	}

	if err = validate.ValidateEncryptKeys(&config.ExternalCfg.EncryptCommon); err != nil {
		log.Fatalf("error validating encrypted: %v", err)
	}

	if err = validateTG(config.NotificationBotToken, config.NotificationRsPayChannel, config.NotificationChannel); err != nil {
		log.Fatalf("error validating tg enviroments: %v", err)
	}

	if err = validate.ValidateMongo(config.ExternalCfg.Database); err != nil {
		log.Fatalf("error validating mongodb: %v", err)
	}
}

// 38 fields
func loadConfig() (*models.Config, error) {
	var config models.Config

	if err := env.Parse(&config); err != nil {
		return nil, err
	}

	return &config, nil
}

func validateURLs(urls []string) error {
	for index, u := range urls {
		if u == "" {
			return fmt.Errorf("empty url, index: %d", index)
		}
		// todo check the liveness of these URLs, many services do not support
	}
	return nil
}

func validateKafka(brokers []string, topic string) error {
	if len(brokers) == 0 {
		return fmt.Errorf("kafka brokers is empty")
	}
	if topic == "" {
		return fmt.Errorf("kafka topic is empty")
	}

	for _, addr := range brokers {
		if addr == "" {
			return fmt.Errorf("empty kafka broker")
		}
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	kafkaTariffClient, err := kgo.NewClient(
		kgo.SeedBrokers(brokers...),
		kgo.ConsumeResetOffset(kgo.NewOffset().AtStart()),
		kgo.DefaultProduceTopic(topic),
		kgo.ConsumeTopics(topic),
	)
	if err != nil {
		return err
	}

	defer kafkaTariffClient.Close()

	err = kafkaTariffClient.Ping(ctx)
	if err != nil {
		return err
	}

	return nil
}

func validateMail(cfg models.MailClientCfg) error {
	if cfg.MailAddress == "" {
		return fmt.Errorf("mail address is empty")
	}

	if cfg.ApiURL == "" {
		return fmt.Errorf("mail api url is empty")
	}

	if cfg.ApiKey == "" {
		return fmt.Errorf("mail api key is empty")
	}

	if cfg.Sender == "" {
		return fmt.Errorf("mail sender is empty")
	}

	client := fiber.AcquireClient()
	req := client.Get("https://api.smtp.bz/v1/user")
	req.Set("Authorization", cfg.ApiKey)

	code, _, _ := req.Bytes()
	if code != fiber.StatusOK {
		return fmt.Errorf("invalid smtp code, no auth: %d", code)
	}

	return nil
}

func validateNotEmpty(config *models.Config) error {
	if config.ExternalCfg.EncryptCommon.PrivKey == "" {
		return fmt.Errorf("invalid private encrypt key")
	}
	if config.ExternalCfg.EncryptCommon.PubKey == "" {
		return fmt.Errorf("invalid publice encrypt key")
	}

	return nil
}

func validateTG(notificationBotToken string, notificationRsPayChannel int64, notificationChannel int64) error {
	err := validate.ValidateTgToken(notificationBotToken)
	if err != nil {
		return err
	}

	if notificationChannel == 0 {
		return fmt.Errorf("notificationChannel is not set")
	}
	if notificationRsPayChannel == 0 {
		return fmt.Errorf("notificationRsPayChannel is not set")
	}

	return nil
}
