package main

import (
	"fmt"
	"strings"
)

// Logger adalah target interface yang diharapkan seluruh kode baru.
// Hanya dua method kecil: level dan pesan.
type Logger interface {
	Log(level, msg string)
}

// LoggerLama adalah API lama milik pihak ketiga: method Print
// menerima argumen apa tanpa konsep level. Kita tidak bisa
// mengubahnya karena kode sumbernya bukan milik kita.
type LoggerLama struct {
	Awalan string
}

// Print milik LoggerLama menggabungkan seluruh argumen lalu mencetak.
func (l *LoggerLama) Print(v ...any) {
	fmt.Println(l.Awalan, fmt.Sprint(v...))
}

// AdapterLogger adalah adapter: mengimplementasi Logger
// dengan mendelegasikan setiap panggilan ke LoggerLama.
type AdapterLogger struct {
	lama *LoggerLama
}

// Log menerjemahkan kontrak baru menjadi kontrak lama:
// level dan pesan digabung menjadi satu argumen Print.
func (a *AdapterLogger) Log(level, msg string) {
	a.lama.Print("[", strings.ToUpper(level), "] ", msg)
}

// Verifikasi saat kompilasi: AdapterLogger wajib memenuhi Logger.
var _ Logger = (*AdapterLogger)(nil)

// Layanan adalah client yang hanya mengenal target interface.
// Layanan tidak tahu menahu soal LoggerLama.
type Layanan struct {
	log Logger
}

func (s *Layanan) Proses(namaTugas string, detik int) {
	s.log.Log("info", "mulai tugas "+namaTugas)
	if detik > 3 {
		s.log.Log("warn", "tugas "+namaTugas+" melebihi batas waktu")
	}
	s.log.Log("info", "tugas "+namaTugas+" selesai")
}

func main() {
	lama := &LoggerLama{Awalan: "app:"}
	svc := &Layanan{log: &AdapterLogger{lama: lama}}
	svc.Proses("sinkronisasi", 5)
}
