package main

import (
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
	"time"

	"code.gitea.io/sdk/gitea"
)

func main() {
	url := os.Getenv("GITEA_URL")
	token := os.Getenv("GITEA_TOKEN")
	repoFullName := os.Getenv("GITEA_REPO") // format: owner/repo
	orgName := os.Getenv("GITEA_ORG")

	if url == "" || token == "" {
		log.Fatal("Missing required environment variables: GITEA_URL, GITEA_TOKEN")
	}

	if repoFullName == "" && orgName == "" {
		log.Fatal("Either GITEA_REPO or GITEA_ORG must be set")
	}

	client, err := gitea.NewClient(url, gitea.SetToken(token))
	if err != nil {
		log.Fatalf("Failed to create Gitea client: %v", err)
	}

	var repos []*gitea.Repository
	if orgName != "" {
		fmt.Printf("Fetching all repositories for organization: %s\n", orgName)
		page := 1
		for {
			orgRepos, _, err := client.ListOrgRepos(orgName, gitea.ListOrgReposOptions{
				ListOptions: gitea.ListOptions{Page: page, PageSize: 50},
			})
			if err != nil {
				log.Fatalf("Failed to fetch organization repositories: %v", err)
			}
			if len(orgRepos) == 0 {
				break
			}
			repos = append(repos, orgRepos...)
			page++
		}
	} else {
		parts := strings.Split(repoFullName, "/")
		if len(parts) != 2 {
			log.Fatal("GITEA_REPO must be in format 'owner/repo'")
		}
		repo, _, err := client.GetRepo(parts[0], parts[1])
		if err != nil {
			log.Fatalf("Failed to fetch repository: %v", err)
		}
		repos = append(repos, repo)
	}

	// Start date for Sprint 1 (2024-10-02)
	startDate := time.Date(2025, 5, 2, 0, 0, 0, 0, time.Local)

	// user -> bucketIndex -> hours
	data := make(map[string]map[int]float64)
	maxBucket := 0

	for _, r := range repos {
		fmt.Printf("Processing repository: %s/%s\n", r.Owner.UserName, r.Name)
		page := 1
		for {
			times, _, err := client.ListRepoTrackedTimes(r.Owner.UserName, r.Name, gitea.ListTrackedTimesOptions{
				ListOptions: gitea.ListOptions{Page: page, PageSize: 50},
			})
			if err != nil {
				fmt.Printf("Warning: Failed to fetch time tracking for %s (page %d): %v\n", r.Name, page, err)
				break
			}
			if len(times) == 0 {
				break
			}

			for _, t := range times {
				if t.Created.Before(startDate) {
					continue
				}

				daysSinceStart := int(t.Created.Sub(startDate).Hours() / 24)
				bucketIndex := daysSinceStart / 14
				if bucketIndex < 0 {
					continue
				}

				if bucketIndex > maxBucket {
					maxBucket = bucketIndex
				}

				userName := t.UserName
				if data[userName] == nil {
					data[userName] = make(map[int]float64)
				}

				hours := float64(t.Time) / 3600.0
				data[userName][bucketIndex] += hours
			}
			page++
		}
	}

	if len(data) == 0 {
		fmt.Println("No time tracking entries found.")
		return
	}

	// Print Table
	users := make([]string, 0, len(data))
	for u := range data {
		users = append(users, u)
	}
	sort.Strings(users)

	// Header
	fmt.Print("\nNutzer       ")
	for i := 0; i <= maxBucket; i++ {
		start := startDate.AddDate(0, 0, i*14)
		fmt.Printf("| %s ", start.Format("02.01."))
	}
	fmt.Println("| Gesamt")
	fmt.Println(strings.Repeat("-", 14+(maxBucket+1)*10+8))

	for _, u := range users {
		fmt.Printf("%-12s ", u)
		total := 0.0
		for i := 0; i <= maxBucket; i++ {
			h := data[u][i]
			total += h
			if h > 0 {
				fmt.Printf("| %7.1fh ", h)
			} else {
				fmt.Printf("| %8s ", "-")
			}
		}
		fmt.Printf("| %7.1fh\n", total)
	}
}
