package main

import (
	"errors"
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// Struct Klasemen menyimpan data poin setiap klub
type Klasemen struct {
	poin       map[string]int
	urutanKlub []string
}

// NewKlasemen sebagai constructor untuk menerima daftar klub
func NewKlasemen(klubKlub []string) *Klasemen {
	k := &Klasemen{
		poin: make(map[string]int),
	}
	for _, nama := range klubKlub {
		k.poin[nama] = 0
		k.urutanKlub = append(k.urutanKlub, nama)
	}
	return k
}

// function parseSkor untuk mengubah string skor seperti "1:0" menjadi dua angka integer
func parseSkor(skor string) (int, int, error) {
	bagian := strings.Split(skor, ":")
	if len(bagian) != 2 {
		return 0, 0, errors.New("format skor tidak validd, gunakan format 'angka:angka'")
	}

	skorKandang, err := strconv.Atoi(strings.TrimSpace(bagian[0]))
	if err != nil {
		return 0, 0, errors.New("skor kandang bukan angka yang valid")
	}

	skorTandang, err := strconv.Atoi(strings.TrimSpace(bagian[1]))
	if err != nil {
		return 0, 0, errors.New("skor tandang bukan angka yang valid")
	}

	return skorKandang, skorTandang, nil
}

// function catatPermainan untuk mencatat hasil pertandingan dan menghitung poin
func (k *Klasemen) catatPermainan(klubKandang, klubTandang, skor string) error {
	skorKandang, skorTandang, err := parseSkor(skor)
	if err != nil {
		return err
	}

	switch {
	case skorKandang > skorTandang:
		k.poin[klubKandang] += 3
	case skorKandang < skorTandang:
		k.poin[klubTandang] += 3
	default: // seri
		k.poin[klubKandang] += 1
		k.poin[klubTandang] += 1
	}

	return nil
}

// struct pasanganKlub digunakan untuk menjaga urutan klub+poin saat di-sort
type pasanganKlub struct {
	nama string
	poin int
}

// function cetakKlasemen mengembalikan daftar klub terurut dari poin tertinggi ke terendah
func (k *Klasemen) cetakKlasemen() []pasanganKlub {
	var hasil []pasanganKlub
	for _, nama := range k.urutanKlub {
		hasil = append(hasil, pasanganKlub{nama: nama, poin: k.poin[nama]})
	}

	sort.SliceStable(hasil, func(i, j int) bool {
		return hasil[i].poin > hasil[j].poin
	})

	return hasil
}

// function ambilPeringkat untuk mengembalikan nama klub di posisi tertentu (1 = teratas)
func (k *Klasemen) ambilPeringkat(nomorPeringkat int) (string, error) {
	klasemen := k.cetakKlasemen()

	if nomorPeringkat < 1 || nomorPeringkat > len(klasemen) {
		return "", fmt.Errorf("peringkat %d tidak ditemukan", nomorPeringkat)
	}

	return klasemen[nomorPeringkat-1].nama, nil
}

func main() {
	klasemen := NewKlasemen([]string{
		"Persija Jakarta",
		"Persib Bandung",
		"Arema FC",
		"Persebaya Surabaya",
	})

	klasemen.catatPermainan("Persija Jakarta", "Persib Bandung", "2:1")
	klasemen.catatPermainan("Arema FC", "Persebaya Surabaya", "2:0")
	klasemen.catatPermainan("Persib Bandung", "Arema FC", "3:3")
	klasemen.catatPermainan("Persebaya Surabaya", "Persija Jakarta", "1:2")
	klasemen.catatPermainan("Persija Jakarta", "Arema FC", "2:3")
	klasemen.catatPermainan("Persib Bandung", "Persebaya Surabaya", "4:2")

	fmt.Println("Klasemen akhir:")
	for _, pasangan := range klasemen.cetakKlasemen() {
		fmt.Printf("%s -> %d\n", pasangan.nama, pasangan.poin)
	}

	peringkat1, err := klasemen.ambilPeringkat(1)
	if err != nil {
		fmt.Println("Error:", err)
	} else {
		fmt.Println("Peringkat 1:", peringkat1)
	}
}