package main

import (
	"bytes"
	"fmt"
	"strings"
	"text/template"
)

// Item adalah satu baris pembelian pada faktur.
type Item struct {
	Nama   string
	Jumlah int
	Harga  int
}

// Subtotal menghitung harga satuan dikali jumlah.
func (it Item) Subtotal() int {
	return it.Jumlah * it.Harga
}

// Faktur merangkum data tagihan seorang pelanggan.
type Faktur struct {
	Nomor     string
	Pelanggan string
	Items     []Item
}

// Total menjumlahkan seluruh subtotal item.
func (f Faktur) Total() int {
	total := 0
	for _, it := range f.Items {
		total += it.Subtotal()
	}
	return total
}

func main() {
	// Tanda {{- dan -}} memangkas spasi serta baris baru
	// di sekitar aksi agar laporan tidak berlubang baris kosong.
	const nota = `FAKTUR {{.Nomor}} — Toko Contoh
Kepada: {{.Pelanggan}}
------------------------------------------
{{- range .Items}}
{{printf "%-18s %3d x Rp%-7d Rp%d" .Nama .Jumlah .Harga .Subtotal}}
{{- end}}
------------------------------------------
TOTAL: Rp{{.Total}}
`

	f := Faktur{
		Nomor:     "INV-2026-001",
		Pelanggan: "Budi Santoso",
		Items: []Item{
			{Nama: "Buku Go", Jumlah: 2, Harga: 95000},
			{Nama: "Mug Keramik", Jumlah: 1, Harga: 45000},
			{Nama: "Stiker Gopher", Jumlah: 5, Harga: 8000},
		},
	}

	t := template.Must(template.New("nota").Parse(nota))
	var buf bytes.Buffer
	if err := t.Execute(&buf, f); err != nil {
		panic(err)
	}
	fmt.Println(buf.String())

	const email = `Dari:    kasir@example.com
Kepada:  {{.Pelanggan}}
Subjek: Faktur {{.Nomor}}

Halo {{.Pelanggan}},

Terima kasih atas pesanan Anda. Rincian pembelian:

{{- range .Items}}
  - {{.Nama}} sejumlah {{.Jumlah}} pcs
{{- end}}

Total tagihan Rp{{.Total}} sudah kami terima.
Simpan email ini sebagai bukti pembelian.
`

	t2 := template.Must(template.New("email").Parse(email))
	var buf2 bytes.Buffer
	if err := t2.Execute(&buf2, f); err != nil {
		panic(err)
	}
	fmt.Println(buf2.String())

	// text/template tidak melakukan escaping apa pun:
	// markup dan tanda kutip dicetak apa adanya.
	const cek = `Teks mentah: {{.}}`
	t3 := template.Must(template.New("cek").Parse(cek))
	var sb strings.Builder
	if err := t3.Execute(&sb, `<b>tebal</b> & "kutip"`); err != nil {
		panic(err)
	}
	fmt.Println(sb.String())
}
