package app

import (
	"backend-agenter/internal/config"
	"backend-agenter/internal/delivery"
	"backend-agenter/internal/repository"
	"backend-agenter/internal/service"
	loadconfig "backend-agenter/pkg/loadconfig"
	"backend-agenter/pkg/logger"
	"log"
	"os"
	"os/signal"
	"syscall"

	"go.uber.org/zap"
)

func Run() {
	log.Println("Starting app ...")
	defer log.Println("Stopping app ...")

	if *config.EnvPath != "" {
		log.Println("Starting app in dev mode")
		err := loadconfig.LoadEnv(*config.EnvPath)
		if err != nil {
			log.Printf("Error while loading local envs: %s", err.Error())
			return
		}
	}

	log.Println("Getting config...")
	config, err := config.New()
	if err != nil {
		log.Printf("Error while getting config: %s", err.Error())
		return
	}

	log.Println("Initializing logger...%s", config.App.Mode)
	err = logger.InitZapLogger(config.App.Mode)
	if err != nil {
		log.Printf("Error while initializing zap logger: %s", err.Error())
		return
	}
	defer logger.Sync()

	db, err := repository.NewClient(config.Postgres)
	if err != nil {
		return
	}
	defer db.Close()

	transportClient, err := repository.NewTransportClient(config.Transport)
	if err != nil {
		return
	}

	repo := repository.New(db, config)
	service := service.New(repo)
	handler := delivery.New(transportClient, service)

	errChan := make(chan error, 1)
	go func() {
		if err := handler.Run(); err != nil {
			zap.S().Errorf("Error running handler: %v", err)
			errChan <- err
		}
	}()

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT)

	select {
	case err := <-errChan:
		zap.S().Errorf("Error running handler: %v", err)
	case s := <-sigs:
		zap.S().Infof("Received signal: %v", s)
	}

	handler.Stop()

}
