package day02

import (
	"fmt"
	"regexp"
	_ "strconv"
	"strings"

	"adventofcode2023/utils"
)

type Set struct {
	Red   int
	Blue  int
	Green int
}

type Game struct {
	ID    int
	Sets []Set
}

func Part1(input string) int {
	sum := 0
	games := []Game{}

	lines := strings.Split(input, "\n")
	for _, line := range lines {
		game, err := parseGame(line)
		if err != nil {
			fmt.Println("Error:", err)
			return -1
		}
		// Print the parsed Game struct
		fmt.Printf("Parsed Game: %+v\n", game)
		games = append(games, game)
	}
	for _, game := range games {
		result := true
		for _, set := range game.Sets {
			if set.Red > 12 || set.Green > 13 || set.Blue > 14 {
				result = false
			}
		}
		if result == true {
			sum += game.ID
		}
	}
	return sum
}

func Part2(input string) int {
	sum := 0
	games := []Game{}

	lines := strings.Split(input, "\n")
	for _, line := range lines {
		game, err := parseGame(line)
		if err != nil {
			fmt.Println("Error:", err)
			return -1
		}
		// Print the parsed Game struct
		fmt.Printf("Parsed Game: %+v\n", game)
		games = append(games, game)
	}
	for _, game := range games {
		maxRed := 0
		maxBlue := 0
		maxGreen := 0
		for _, set := range game.Sets {
			if set.Red > maxRed {
				maxRed = set.Red
			}
			if set.Blue > maxBlue {
				maxBlue = set.Blue
			}
			if set.Green > maxGreen {
				maxGreen = set.Green
			}		
		}
		sum +=  maxRed * maxBlue * maxGreen
	}
	return sum
}

func parseGame(input string) (Game, error) {
	var game Game

	// Extract ID
	reID := regexp.MustCompile(`Game (\d+):(.*)`)
	matchID := reID.FindStringSubmatch(input)
	if len(matchID) != 3 {
		return game, fmt.Errorf("unable to extract game ID")
	}
	game.ID = utils.MustAtoi(matchID[1])
	setsString := strings.Split(matchID[2], ";")
	for _, setString := range setsString {
		var set Set
		// Extract colors and quantities
		reColors := regexp.MustCompile(`(\d+) (\w+)`)
		matches := reColors.FindAllStringSubmatch(setString, -1)
		for _, match := range matches {
			color := strings.ToLower(match[2])
			switch color {
			case "red":
				set.Red = utils.MustAtoi(match[1])
			case "blue":
				set.Blue = utils.MustAtoi(match[1])
			case "green":
				set.Green = utils.MustAtoi(match[1])
			default:
				return game, fmt.Errorf("unknown color: %s", color)
			}
		}
		game.Sets = append(game.Sets, set)
	}
	return game, nil
}