package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
)

type Pendaftaran struct {
	NamaLengkap *string      `json:"nama_lengkap"`
	Email       *string      `json:"email"`
	Umur        *int         `json:"umur"`
	Skor        *json.Number `json:"skor"`
	Alamat      string       `json:"alamat"`
}

func (p Pendaftaran) Validate() error {
	var galat []error
	if p.NamaLengkap == nil {
		galat = append(galat, errors.New("nama_lengkap wajib diisi"))
	} else if len(*p.NamaLengkap) < 3 {
		galat = append(galat, fmt.Errorf("nama_lengkap minimal 3 huruf, dapat %d", len(*p.NamaLengkap)))
	}
	if p.Email == nil {
		galat = append(galat, errors.New("email wajib diisi"))
	} else if !strings.Contains(*p.Email, "@") {
		galat = append(galat, fmt.Errorf("email %q tidak memuat tanda @", *p.Email))
	}
	if p.Umur == nil {
		galat = append(galat, errors.New("umur wajib diisi"))
	} else if *p.Umur < 17 || *p.Umur > 90 {
		galat = append(galat, fmt.Errorf("umur harus di rentang 17-90, dapat %d", *p.Umur))
	}
	if p.Skor != nil {
		nilai, err := p.Skor.Float64()
		if err != nil || nilai < 0 || nilai > 100 {
			galat = append(galat, fmt.Errorf("skor harus angka 0-100, dapat %s", *p.Skor))
		}
	}
	return errors.Join(galat...)
}

func prosesDokumen(dokumen string) {
	var p Pendaftaran
	if err := json.Unmarshal([]byte(dokumen), &p); err != nil {
		fmt.Println("decode gagal:", err)
		return
	}
	if err := p.Validate(); err != nil {
		fmt.Println("validasi ditolak:")
		for _, baris := range strings.Split(err.Error(), "\n") {
			fmt.Println("  -", baris)
		}
		return
	}
	fmt.Printf("validasi lolos: nama=%s umur=%d skor=%s\n",
		*p.NamaLengkap, *p.Umur, p.Skor.String())
}

func main() {
	gagal := `{
		"nama_lengkap": "Bo",
		"email": "budi.example.com",
		"umur": 15,
		"skor": 120,
		"kota": "Bandung"
	}`
	prosesDokumen(gagal)

	lolos := `{
		"nama_lengkap": "Budi Santoso",
		"email": "budi@example.com",
		"umur": 25,
		"skor": 87.5,
		"alamat": "Jl. Merdeka No. 1"
	}`
	prosesDokumen(lolos)

	tanpaUmur := `{"nama_lengkap":"Siti Aminah","email":"siti@example.com"}`
	prosesDokumen(tanpaUmur)

	kosong := `{}`
	prosesDokumen(kosong)
}
