package main

import (
	"fmt"
	"github.com/andygrunwald/go-jira"
	"github.com/charmbracelet/huh"
	"github.com/fatih/color"
	"github.com/spf13/viper"
	"os"
	"strconv"
)

var red = color.New(color.FgRed).SprintFunc()
var yellow = color.New(color.FgYellow).SprintFunc()

func printError(msg string, err error) {
	if err == nil {
		fmt.Printf("Error: %s\n", msg)
	} else {
		fmt.Printf("Error: %s: %v\n", msg, err)
	}
}

func ActionExit(_ []string) {
	promptRunner.Close()
	os.Exit(0)
}

func ActionLogout(_ []string) {
	viper.Set("token", nil)
	err := viper.WriteConfig()
	if err != nil {
		printError("Failed to write config", err)
	}
	ensureLoggedIn()
}

func ActionListProjects(_ []string) {
	projects, _, err := jiraClient.Project.GetList()
	if err != nil {
		printError("Failed to list projects", err)
		return
	}
	for _, project := range *projects {
		fmt.Printf(" - %s: %s\n", project.Key, project.Name)
	}
}

func ActionUseProject(args []string) {
	var projectId string
	if len(args) == 0 {
		println("Fetching projects...")
		projects, _, err := jiraClient.Project.GetList()
		if err != nil {
			printError("Failed to list projects", err)
			return
		}

		options := []huh.Option[string]{}
		for _, p := range *projects {
			name := fmt.Sprintf("%s - %s", red(p.Key), p.Name)
			options = append(options, huh.NewOption(name, p.ID))
		}

		err = huh.NewSelect[string]().
			Title("Choose a project").
			Options(options...).
			Value(&projectId).
			Run()
		if err != nil {
			printError("Failed to choose project", err)
			return
		}
	} else if len(args) == 1 {
		projectId = args[0]
	} else {
		printError("Need a project ID", nil)
		return
	}
	project, _, err := jiraClient.Project.Get(projectId)
	if err != nil {
		printError("Failed to get project", err)
		return
	}
	fmt.Printf("Using project %s (%s)\n", project.Name, project.Key)
	SetProject(project)
	SaveConfig()
	UpdatePrompt()
}

func ActionListBoards(_ []string) {
	project := GetProjectId()
	if project == "" {
		printError("Please select a project first", nil)
		return
	}
	list, _, err := jiraClient.Board.GetAllBoards(&jira.BoardListOptions{ProjectKeyOrID: project})
	if err != nil {
		printError("Failed to list boards", err)
		return
	}
	for _, board := range list.Values {
		fmt.Printf(" - %s (%d)\n", board.Name, board.ID)
	}
}

func ActionUseBoard(args []string) {
	if len(args) != 1 {
		printError("Need a board ID", nil)
		return
	}
	boardId, err := strconv.ParseInt(args[0], 10, 64)
	if err != nil {
		printError("Invalid board ID", nil)
		return
	}
	board, _, err := jiraClient.Board.GetBoardConfiguration(int(boardId))
	if err != nil {
		printError("Failed to get project", err)
		return
	}
	fmt.Printf("Using board %s (%d)\n", board.Name, board.ID)
	SetBoard(board.ID, board.Name)
	SaveConfig()
	UpdatePrompt()
}

func ActionUseCurrentSprint(_ []string) {
	boardId := viper.GetInt("board.id")
	list, _, err := jiraClient.Board.GetAllSprintsWithOptions(boardId, &jira.GetAllSprintsOptions{
		State: "active",
	})
	if err != nil {
		printError("Failed to get current board", err)
		return
	}
	if len(list.Values) != 1 {
		printError("There should be only one sprint at a time", nil)
		return
	}
	sprint := list.Values[0]
	fmt.Printf("Using sprint %s (%d)\n", sprint.Name, sprint.ID)
	SetSprint(sprint)
	SaveConfig()
	UpdatePrompt()
}

func ActionListIssues(_ []string) {
	sprintId := GetSprintId()
	if sprintId == 0 {
		printError("No sprint selected", nil)
		return
	}
	issues, _, err := jiraClient.Sprint.GetIssuesForSprint(sprintId)
	if err != nil {
		printError("Failed to list issues", err)
	}
	for _, issue := range issues {
		fmt.Printf("%s - %s (%s)\n", red(issue.Key), issue.Fields.Summary, yellow(issue.Fields.Status.Name))
	}
}