package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"ticket-pimp/bot/handler"
	discordbot "ticket-pimp/discord-bot"
	"ticket-pimp/internal/services"

	"github.com/joho/godotenv"
	"github.com/mr-linch/go-tg"
	"github.com/mr-linch/go-tg/tgb"
)

func main() {
	log.Print("started")
	env("develop.env")

	if err := runDiscrodBot(); err != nil {
		log.Fatal(fmt.Errorf("discord bot cannot be runned: %v", err))
	}

	ctx := context.Background()

	ctx, cancel := signal.NotifyContext(ctx, os.Interrupt, os.Kill, syscall.SIGTERM)
	defer cancel()

	if err := runTgBot(ctx); err != nil {
		fmt.Println(err)
		defer os.Exit(1)
	}
}

// env
// env function reads provided file and setup envirmental variables;
func env(envFilePath string) {
	err := godotenv.Load(envFilePath)
	if err != nil {
		log.Fatal("Error while loading env file")
	}
}

func runDiscrodBot() error {
	token := os.Getenv("DISCORD_TOKEN")

	dbot, err := discordbot.NewDiscordBot(token)
	if err != nil {
		return err
	}

	createRepoHandler := discordbot.CreateRepoHandler(3)

	dbot.Session.AddHandler(createRepoHandler.Handler)

	if err := dbot.Session.Open(); err != nil {
		return fmt.Errorf("cannot open the session: %v", err)
	}

	log.Println("Adding commands...")
	cmd, err := dbot.Session.ApplicationCommandCreate(dbot.Session.State.User.ID, "", &createRepoHandler.Command)
	if err != nil {
		log.Panicf("Cannot create '%v' command: %v", createRepoHandler.Command.Name, err)
	}

	defer dbot.Session.Close()
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, os.Interrupt)
	<-stop
	log.Println("Graceful shutdown")

	log.Println("Removing commands...")
	err = dbot.Session.ApplicationCommandDelete(dbot.Session.State.User.ID, "", cmd.ID)
	if err != nil {
		log.Panicf("Cannot delete '%v' command: %v", cmd.Name, err)
	}

	return nil
}

// runTgBot ...
// ..function creates new Telegram BOT instance
// ..throw env variables through bot's handlers
// ..setup tg bot router;
// and finally returns tgb.Poller
func runTgBot(ctx context.Context) error {

	client := tg.New(os.Getenv("TG_API"))

	gitService := services.NewGit(
		os.Getenv("GIT_BASE_URL"),
		os.Getenv("GIT_TOKEN"),
	)

	cloudService := services.NewCloud(
		os.Getenv("CLOUD_BASE_URL"),
		os.Getenv("CLOUD_USER"),
		os.Getenv("CLOUD_PASS"),
	)

	coda := services.NewCodaClient(
		os.Getenv("CODA_TOKEN1"),
	)

	h := handler.NewHandler(
		gitService,
		cloudService,
		coda,
	)

	router := tgb.NewRouter().
		Message(h.Init, tgb.Command("init")).
		Message(h.PingHandler, tgb.Command("ping")).
		Message(h.DevelopmentTaskHandler, tgb.TextHasPrefix("/new")).
		Message(h.NewRepoHandler, tgb.TextHasPrefix("/repo")).
		Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")).
		Message(h.FarmTaskHandler, tgb.TextHasPrefix("/task"))

	return tgb.NewPoller(
		router,
		client,
	).Run(ctx)
}
