package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

type Equation struct {
	result  int
	numbers []int
}

func readInput(file *os.File) []Equation {
	scanner := bufio.NewScanner(file)
	var equations []Equation

	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			break
		}

		var equation Equation
		parts := strings.Split(line, ": ")
		if len(parts) != 2 {
			log.Fatalf("Bad input: %s", line)
		}

		var err error
		equation.result, err = strconv.Atoi(parts[0])
		if err != nil {
			log.Fatalf("Problem parsing '%s': %s", parts[0], err)
		}

		numbers := strings.Split(parts[1], " ")
		for _, number := range numbers {
			item, err := strconv.Atoi(number)
			if err != nil {
				log.Fatalf("Problem parsing '%s': %s", number, err)
			}

			equation.numbers = append(equation.numbers, item)
		}

		equations = append(equations, equation)
	}

	return equations
}

func concatenate(a, b int) int {
	if a == 0 {
		return b
	}

	result, _ := strconv.Atoi(fmt.Sprintf("%d%d", a, b))
	return result
}

func check(equation Equation, index, result int, conc bool) bool {
	if result > equation.result {
		return false
	}

	if index >= len(equation.numbers) {
		if result == equation.result {
			return true
		}

		return false
	}

	resultAdd := check(equation, index+1, result+equation.numbers[index], conc)

	resultConc := false
	if conc {
		resultConc = check(equation, index+1, concatenate(result, equation.numbers[index]), conc)
	}

	if result == 0 {
		result++
	}
	resultMul := check(equation, index+1, result*equation.numbers[index], conc)

	if resultAdd {
		return resultAdd
	}

	if resultConc {
		return resultConc
	}

	return resultMul
}

func parts(equations []Equation) (int, int) {
	var part1 int
	var toRecheck []Equation
	for _, equation := range equations {
		if check(equation, 0, 0, false) {
			part1 += equation.result
		} else {
			toRecheck = append(toRecheck, equation)
		}
	}

	part2 := part1
	for _, equation := range toRecheck {
		if check(equation, 0, 0, true) {
			part2 += equation.result
		}
	}

	return part1, part2
}

func main() {
	if len(os.Args) < 2 {
		log.Fatal("You need to specify a file!")
	}

	filePath := os.Args[1]
	file, err := os.Open(filePath)
	if err != nil {
		log.Fatalf("Failed to open %s!\n", filePath)
	}

	equations := readInput(file)
	part1, part2 := parts(equations)
	fmt.Println("Part1:", part1)
	fmt.Println("Part2:", part2)
}