package cmd

import (
	"axolotl/models"
	"axolotl/service"
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

var (
	uTitle, uContent, uDue               string
	uClearDue                            bool
	uStatus, uPrio, uType                string
	uNamespace, uAssignee                string
	uAddTags, uRmTags, uAddRels, uRmRels []string
)

var updateCmd = &cobra.Command{
	Use: "update <id>", Short: "Update a node", Args: cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		svc, err := getNodeService()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}

		var input service.UpdateInput

		if cmd.Flags().Changed("title") {
			input.Title = &uTitle
		}
		if cmd.Flags().Changed("content") {
			input.Content = &uContent
		}
		if cmd.Flags().Changed("due") {
			input.DueDate = &uDue
		}
		if uClearDue {
			empty := ""
			input.DueDate = &empty
		}

		// --tag / --tag-remove are aliases for --rel / --rel-remove with no target.
		for _, tag := range uAddTags {
			input.AddRels = append(input.AddRels, service.RelInput{Type: models.RelType(tag), Target: ""})
		}
		for _, tag := range uRmTags {
			input.RemoveRels = append(input.RemoveRels, service.RelInput{Type: models.RelType(tag), Target: ""})
		}

		// Shorthand flags expand to property rels or edge rels.
		if cmd.Flags().Changed("type") {
			input.AddRels = append(input.AddRels, service.RelInput{Type: models.RelType("_type::" + uType), Target: ""})
		}
		if cmd.Flags().Changed("status") {
			input.AddRels = append(input.AddRels, service.RelInput{Type: models.RelType("_status::" + uStatus), Target: ""})
		}
		if cmd.Flags().Changed("prio") {
			input.AddRels = append(input.AddRels, service.RelInput{Type: models.RelType("_prio::" + uPrio), Target: ""})
		}
		if cmd.Flags().Changed("namespace") {
			input.Namespace = &uNamespace
		}
		if cmd.Flags().Changed("assignee") {
			input.AddRels = append(input.AddRels, service.RelInput{Type: models.RelAssignee, Target: uAssignee})
		}

		for _, r := range uAddRels {
			ri, err := parseRelInput(r)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				return
			}
			input.AddRels = append(input.AddRels, ri)
		}
		for _, r := range uRmRels {
			ri, err := parseRelInput(r)
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				return
			}
			input.RemoveRels = append(input.RemoveRels, ri)
		}

		n, err := svc.Update(args[0], input)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
		PrintNode(cmd.OutOrStdout(), svc, n, jsonFlag)
	},
}

func init() {
	rootCmd.AddCommand(updateCmd)
	f := updateCmd.Flags()
	f.StringVar(&uTitle, "title", "", "new title")
	f.StringVar(&uContent, "content", "", "new content")
	f.StringVar(&uDue, "due", "", "due date")
	f.BoolVar(&uClearDue, "clear-due", false, "clear due date")
	f.StringVar(&uStatus, "status", "", "status (open, done)")
	f.StringVar(&uPrio, "prio", "", "priority (high, medium, low)")
	f.StringVar(&uType, "type", "", "node type")
	f.StringVar(&uNamespace, "namespace", "", "namespace name or ID")
	f.StringVar(&uAssignee, "assignee", "", "assignee username or ID")
	f.StringArrayVar(&uAddTags, "tag", nil, "add label tag (alias for --rel tagname)")
	f.StringArrayVar(&uRmTags, "tag-remove", nil, "remove label tag")
	f.StringArrayVar(&uAddRels, "rel", nil, "add relation (prefix::value or relname:target)")
	f.StringArrayVar(&uRmRels, "rel-remove", nil, "remove relation (prefix::value or relname:target)")
}
