// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package lunatask

import (
	"errors"
	"fmt"
	"strings"
)

// Eisenhower represents a quadrant in the Eisenhower priority matrix, which
// categorizes tasks by whether they are urgent (time-sensitive) and/or
// important (valuable toward your goals).
//
// The four quadrants guide what action to take:
//
//	                  | Urgent        | Not Urgent
//	------------------|---------------|-------------
//	Important         | Do Now (1)    | Do Later (3)
//	Not Important     | Delegate (2)  | Eliminate (4)
//
// Use [NewEisenhower] to compute the quadrant from boolean flags, or the
// builder methods [TaskBuilder.Important] and [TaskBuilder.Urgent] for a
// fluent API.
type Eisenhower int

// Eisenhower matrix quadrants. See [Eisenhower] for the full matrix.
const (
	EisenhowerUncategorized Eisenhower = 0 // not yet categorized
	EisenhowerDoNow         Eisenhower = 1 // urgent + important
	EisenhowerDelegate      Eisenhower = 2 // urgent, not important
	EisenhowerDoLater       Eisenhower = 3 // important, not urgent
	EisenhowerEliminate     Eisenhower = 4 // neither urgent nor important
)

// NewEisenhower returns the quadrant for the given flags:
//
//	NewEisenhower(true, true)   // DoNow
//	NewEisenhower(true, false)  // DoLater
//	NewEisenhower(false, true)  // Delegate
//	NewEisenhower(false, false) // Eliminate
func NewEisenhower(important, urgent bool) Eisenhower {
	switch {
	case important && urgent:
		return EisenhowerDoNow
	case urgent:
		return EisenhowerDelegate
	case important:
		return EisenhowerDoLater
	default:
		return EisenhowerEliminate
	}
}

// String returns a human-readable description of the Eisenhower quadrant.
func (e Eisenhower) String() string {
	switch e {
	case EisenhowerUncategorized:
		return "uncategorized"
	case EisenhowerDoNow:
		return "do now (important + urgent)"
	case EisenhowerDelegate:
		return "delegate (urgent)"
	case EisenhowerDoLater:
		return "do later (important)"
	case EisenhowerEliminate:
		return "eliminate"
	default:
		return fmt.Sprintf("Eisenhower(%d)", e)
	}
}

// IsUrgent reports whether e is in an urgent quadrant ([EisenhowerDoNow] or [EisenhowerDelegate]).
func (e Eisenhower) IsUrgent() bool {
	return e == EisenhowerDoNow || e == EisenhowerDelegate
}

// IsImportant reports whether e is in an important quadrant ([EisenhowerDoNow] or [EisenhowerDoLater]).
func (e Eisenhower) IsImportant() bool {
	return e == EisenhowerDoNow || e == EisenhowerDoLater
}

// Errors returned by Eisenhower operations.
var (
	// ErrInvalidEisenhower is returned when parsing an unknown Eisenhower quadrant string.
	ErrInvalidEisenhower = errors.New("invalid eisenhower quadrant")
)

// ParseEisenhower parses a string to an Eisenhower quadrant value (case-insensitive).
// Valid values: "uncategorized", "do-now", "delegate", "do-later", "eliminate",
// as well as numeric strings "0" through "4".
func ParseEisenhower(str string) (Eisenhower, error) {
	switch strings.ToLower(str) {
	case "uncategorized", "0":
		return EisenhowerUncategorized, nil
	case "do-now", "donow", "1":
		return EisenhowerDoNow, nil
	case "delegate", "2":
		return EisenhowerDelegate, nil
	case "do-later", "dolater", "3":
		return EisenhowerDoLater, nil
	case "eliminate", "4":
		return EisenhowerEliminate, nil
	default:
		return 0, fmt.Errorf("%w: %q", ErrInvalidEisenhower, str)
	}
}
