package main

import (
	"context"
	"os"
	"os/signal"
	"syscall"

	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/bot/telegram"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/config"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/logger"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/provider/bybit"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/repository/postgresql"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/service/alerter"
	"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/usecase"
)

func main() {
	ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer cancel()

	// config
	cfg := config.MustLoad()

	// logger
	log := logger.NewAppLogger(&cfg.Logger)
	log.Info("app started")

	// storage
	storage, err := postgresql.New(ctx, log, &cfg.Postgresql)
	if err != nil {
		log.Error("failed to connect to postgresql", "err", err)
		os.Exit(1)
	}

	// usecases
	uc := usecase.New(log, storage)

	// price provider
	priceProvider := bybit.New(log, &cfg.Providers.Bybit)

	// telegram bot
	bot, err := telegram.New(cfg.Telegram.Token, log, uc, priceProvider)
	if err != nil {
		log.Error("failed to create telegram bot", "err", err)
		os.Exit(1)
	}

	// alerter service — bot acts as the notifier
	al := alerter.New(log, priceProvider, bot, storage)

	// inject alerter into bot to keep the cache in sync when alerts are created/removed
	bot.SetAlerter(al)

	// load existing active alerts into the alerter cache
	if err := al.LoadAlerts(ctx); err != nil {
		log.Error("failed to load alerts", "err", err)
		os.Exit(1)
	}

	// start background price-checking loop
	al.Run(ctx)

	// run bot (blocks until ctx is cancelled)
	bot.Run(ctx)

	log.Info("app stopped")
}
