package main

import (
	"database/sql"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
	"git.lukegb.com/lukegb/depot/web/barf/frontend/barfdb"

	_ "github.com/mattn/go-sqlite3"
)

var (
	db         *barfdb.DB
	flagDBPath string
)

var rootCmd = &cobra.Command{
	Use:   "barfcli",
	Short: "BARF is the Birthday Activities Registration Form",
	Long:  `Manage your Birthday Activities`,
}

var initializeCmd = &cobra.Command{
	Use:   "initialize",
	Short: "Initialize a new database",
	Args:  cobra.ExactArgs(0),
	RunE: func(cmd *cobra.Command, args []string) error {
		return db.Initialize(cmd.Context())
	},
}

var addCmd = &cobra.Command{
	Use:   "add keyprefix name",
	Short: "Add a new key",
	Args:  cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx := cmd.Context()
		key, err := db.GetOrCreateKey(ctx, args[0], &barfdb.Dataset{Name: args[1]})
		if err != nil {
			return err
		}
		fmt.Println(key)
		return nil
	},
}

var lsCmd = &cobra.Command{
	Use:   "ls",
	Short: "List keys and respondents",
	Args:  cobra.ExactArgs(0),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx := cmd.Context()
		entries, err := db.List(ctx)
		if err != nil {
			return err
		}
		maxLengths := []int{
			len("basekey"),
			len("key"),
			len("name"),
		}
		for _, entry := range entries {
			for n, l := range []int{
				len(entry.BaseKey()),
				len(entry.FullKey),
				len(entry.Dataset.Name),
			} {
				if maxLengths[n] < l {
					maxLengths[n] = l
				}
			}
		}
		fmtFmt := fmt.Sprintf("%%-%ds\t%%-%ds\t%%-%ds\t%%v\n", maxLengths[0], maxLengths[1], maxLengths[2])
		fmt.Printf(fmtFmt, "basekey", "key", "name", "completed")
		fmt.Printf(fmtFmt, strings.Repeat("-", maxLengths[0]), strings.Repeat("-", maxLengths[1]), strings.Repeat("-", maxLengths[2]), "---------")
		for _, entry := range entries {
			fmt.Printf(fmtFmt, entry.BaseKey(), entry.FullKey, entry.Dataset.Name, entry.Completed())
		}
		return nil
	},
}

var getCmd = &cobra.Command{
	Use:   "get short",
	Short: "Get responses for a user",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx := cmd.Context()
		resp, err := db.GetResponseForShortKey(ctx, args[0])
		if err != nil {
			return err
		}
		hs, err := resp.HumanString()
		if err != nil {
			return err
		}
		fmt.Println(hs)
		return nil
	},
}

func openDB() {
	sdb, err := sql.Open("sqlite3", flagDBPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Opening database %v: %v\n", flagDBPath, err)
		os.Exit(1)
		return
	}
	db = barfdb.New(sdb)
}

func closeDB() {
	db.Close()
}

func init() {
	cobra.OnInitialize(openDB)
	cobra.OnFinalize(closeDB)

	rootCmd.PersistentFlags().StringVar(&flagDBPath, "db", "/var/lib/barf-fe/db.db", "BARF database.")

	rootCmd.AddCommand(initializeCmd, addCmd, lsCmd, getCmd)
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}