Project, Task and Time management
package main

import (
	"fmt"
	"context"
	"strings"

	db "github.com/Asfolny/protastim/internal/database"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
	"github.com/charmbracelet/bubbles/list"
	"github.com/charmbracelet/bubbles/spinner"
)

func fetchProjects(queries *db.Queries, source string) tea.Cmd {
	return func() tea.Msg {
		rows, err := queries.ProjectsWithRecName(context.Background())
		if err != nil {
			return errMsg{err}
		}

		items := make([]list.Item, len(rows))
		for i, e := range rows {
			var desc strings.Builder

			if e.ParentTree.Valid {
				desc.WriteString(fmt.Sprintf("Parent: %s", e.ParentTree.String))
				if e.DueAt.Valid {
					desc.WriteString("\n")
				}
			}

			if e.DueAt.Valid {
				desc.WriteString(fmt.Sprintf("Due: %s", e.DueAt.Time.Format("2006/02/01")))
			}

			items[i] = listItem{
				title: e.Name,
				desc: desc.String(),
				id: e.ID,
				started: e.StartAt.Valid,
				completed: e.CompletedAt.Valid,
			}
		}

		return selectorItemsMsg{source, items}
	}
}


type startedProjectMsg int64
func startProject(queries *db.Queries, id int64) tea.Cmd {
	return func() tea.Msg {
		err := queries.StartProject(context.Background(), id)
		if err != nil {
			return errMsg{err}
		}

		return startedProjectMsg(id)
	}
}

type completedProjectMsg int64
func completeProject(queries *db.Queries, id int64) tea.Cmd {
	return func() tea.Msg {
		err := queries.CompleteProject(context.Background(), id)
		if err != nil {
			return errMsg{err}
		}

		return completedProjectMsg(id)
	}
}

func newProjectSelector(config *config, width int, height int, source string) selector {
	model := selector{config: config, width: width, height: height, fetchFunc: fetchProjects(config.queries, source), tracking: source}

	delegate := list.NewDefaultDelegate()
	delegate.SetHeight(2)
	statusStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#04B575"))

	delegate.UpdateFunc = func(msg tea.Msg, list *list.Model) tea.Cmd {
		item, ok := list.SelectedItem().(listItem)
		if !ok {
			return nil
		}

		switch msg := msg.(type) {
		case tea.KeyMsg:
			switch msg.String() {
			case "S":
				if item.started {
					return nil
				}

				return tea.Batch(
					list.NewStatusMessage(statusStyle.Render("Starting " + item.title)),
					startProject(config.queries, item.id),
				)

			case "C":
				if item.completed {
					return nil
				}

				return tea.Batch(
					list.NewStatusMessage(statusStyle.Render("Completing " + item.title)),
					completeProject(config.queries, item.id),
				)
			}
		}

		return nil
	}

	selectorList := list.New(make([]list.Item, 0), delegate, width, height)
	selectorList.Title = "Projects"
	selectorList.Styles.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("#FFFDF5")).Background(lipgloss.Color("#25A065")).Padding(0, 1)
	selectorList.Styles.NoItems = lipgloss.NewStyle().Padding(0, 2).Foreground(lipgloss.Color("#626262"))
	selectorList.Styles.Spinner = lipgloss.NewStyle().Foreground(lipgloss.Color("#04B575"))
	selectorList.SetShowHelp(false)
	selectorList.SetSpinner(spinner.MiniDot)
	model.list = selectorList

	return model
}