// Package batch contains the non-interactive maintenence commands.
package batch

import (
	"context"
	_ "embed"
	"errors"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"

	"git.lyda.ie/kevin/bulletin/ask"
	"git.lyda.ie/kevin/bulletin/key"
	"git.lyda.ie/kevin/bulletin/storage"
	"github.com/adrg/xdg"
)

//go:embed crontab
var crontabTemplate string

// Reboot deletes all messages with `shutdown` set.
func Reboot() int {
	fmt.Println("TODO: Delete messages with shutdown != 0.")
	return 0
}

// Expire deletes all messages that have hit their expiration date.
func Expire() int {
	fmt.Println("TODO: expire messages.")
	return 0
}

// Install is an interactive command used to install the crontab.
func Install() int {
	// Check if install has run before.
	touchfile := path.Join(xdg.Home, ".bulletin-installed")
	if _, err := os.Stat(touchfile); err == nil {
		ask.CheckErr(errors.New("~/.bulletin-installed exists; BULLETIN install has run"))
	} else {
		if !errors.Is(err, os.ErrNotExist) {
			fmt.Println("ERROR: Unknown error checking in ~/.bulletin-installed exists.")
			fmt.Println("ERROR: Can't see if BULLETIN has been installed.")
			ask.CheckErr(err)
		}
	}

	// Connect to the database.
	store, err := storage.Open()
	ask.CheckErr(err)
	q := storage.New(store.DB)

	// Create the initial users.
	login, err := ask.GetLine("Enter login of initial user: ")
	ask.CheckErr(err)
	name, err := ask.GetLine("Enter name of initial user: ")
	ask.CheckErr(err)
	sshkey, err := ask.GetLine("Enter ssh public key of initial user: ")
	ask.CheckErr(err)

	// Seed data.
	ctx := context.TODO()
	ask.CheckErr(q.SeedUserSystem(ctx))
	ask.CheckErr(q.SeedFolderGeneral(ctx))
	ask.CheckErr(q.SeedGeneralOwner(ctx))
	_, err = q.AddUser(ctx, storage.AddUserParams{
		Login: login,
		Name:  name,
	})
	ask.CheckErr(q.SeedGeneralOwner(ctx))
	key.Add(login, sshkey)

	// Install crontab.
	bulletin, err := os.Executable()
	if err != nil {
		panic(err) // TODO: cleanup error handling.
	}
	crontab := &strings.Builder{}
	template.Must(template.New("crontab").Parse(crontabTemplate)).
		Execute(crontab, map[string]string{"Bulletin": bulletin})
	fmt.Printf("Add this to crontab:\n\n%s\n", crontab.String())
	err = installCrontab(crontab.String())
	if err != nil {
		panic(err) // TODO: cleanup error handling.
	}

	// Mark that install has happened.
	err = touch(touchfile)
	if err != nil {
		panic(err) // TODO: cleanup error handling.
	}

	return 0
}