package main

import (
	"context"
	"embed"
	"errors"
	"fmt"
	"ld/eventbus"
	"ld/server"
	"ld/sqlite"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
)

const (
	exitCodeErr       = 1
	exitCodeInterrupt = 2
)

var AppRoot = "./" // path for supporting files that sit in app root folder in production

//go:embed frontend/*
var frontend embed.FS

//go:embed embed
var embedded embed.FS

// main specific variables
var ExecutableName string

func main() {

	fmt.Println("Developement mode")

	err := errors.New("")

	ExecutableName, err = getExecutableName()
	if err != nil {
		os.Exit(exitCodeErr)
	}

	// setting up logging to file
	logFileName := AppRoot + ExecutableName + ".log"
	logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Printf("error opening file: %v", err)
		os.Exit(exitCodeErr)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	err = run()
	if err != nil {
		os.Exit(exitCodeErr)
	}

	run()

}

func run() error {

	ctx := context.Background()

	stateDB, err := createStateDB(true)
	if err != nil {
		log.Fatalf("Failed to create internal StateDB: %v", err)
	}

	ebus := eventbus.NewEventBus()

	/*
		type Server struct {
			Ctx        context.Context
			StateDB    *sqlite.Database
			Static     fs.FS
			Embedded   embed.FS
			intervalID int
			Ebus       *eventbus.EventBus
			Templ      *template.Template
			Mux        *http.ServeMux
			}
	*/

	// setting up the server

	server, err := server.New(
		ctx,
		stateDB,
		embedded,
		ebus,
	)

	if err != nil {
		log.Fatalf("server-app not created - error: %v", err)
	}

	// tasks.SetupTasks(server)

	err = server.Start()
	if err != nil {
		fmt.Printf("server not started - error: %v \n", err)
		log.Fatalf("server not started - error: %v", err)
	}

	readCrew(server)
	readMessages(server)
	// return nil

	// listen for os shutdown events, report them into log file and exit application
	chanOS := make(chan os.Signal, 2)
	signal.Notify(chanOS, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-chanOS
		log.Println("shutting down request signal received")
		server.Close()
		os.Exit(exitCodeInterrupt)
	}()

	// setting up the routes, hooking up API endpoints with backend functions
	// routes.SetupRoutes(server)

	return nil

}

// some internal functions

func getExecutableName() (string, error) {
	name, err := os.Executable()
	if err != nil {
		return "", err
	}
	name = filepath.Base(name)
	return strings.TrimSuffix(name, filepath.Ext(name)), nil
}

func createStateDB(ctx context.Context) (*sqlite.Database, error) {

	fileName := "state.db"

	db := sqlite.New(fileName)

	err := db.Open(ctx)
	if err != nil {
		return nil, err
	}

	query, err := embedded.ReadFile("embed/create_state_db.sql")
	if err != nil {
		return nil, err
	}

	_, err = db.DB().Exec(string(query))
	if err != nil {
		return nil, err
	}

	return db, nil
}
