package main

import (
	"errors"
	"fmt"
)

// ErrTerlaluPercobaan adalah sentinel untuk limit transaksi.
var ErrTerlaluPercobaan = errors.New("terlalu banyak percobaan")

// ErrorTransfer membawa data transaksi untuk keputusan bisnis.
type ErrorTransfer struct {
	Rekening string
	Jumlah   int
}

func (e *ErrorTransfer) Error() string {
	return fmt.Sprintf("transfer %s sebesar Rp%d gagal", e.Rekening, e.Jumlah)
}

func prosesTransfer(rekening string, jumlah int) error {
	if jumlah > 5_000_000 {
		return fmt.Errorf("validasi jumlah: %w", ErrTerlaluPercobaan)
	}
	if jumlah < 10_000 {
		return &ErrorTransfer{Rekening: rekening, Jumlah: jumlah}
	}
	return nil
}

func layananTransfer(rekening string, jumlah int) error {
	if err := prosesTransfer(rekening, jumlah); err != nil {
		return fmt.Errorf("layanan transfer: %w", err)
	}
	return nil
}

func main() {
	err := layananTransfer("BRI-001", 7_500_000)
	fmt.Println("A:", err)
	fmt.Println("   errors.Is ErrTerlaluPercobaan:", errors.Is(err, ErrTerlaluPercobaan))

	err = layananTransfer("BRI-001", 5_000)
	fmt.Println("B:", err)

	var et *ErrorTransfer
	if errors.As(err, &et) {
		fmt.Println("   errors.As -> rekening:", et.Rekening, "jumlah:", et.Jumlah)
	}

	_, ok := err.(*ErrorTransfer)
	fmt.Println("   type assertion langsung:", ok)
}
