package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// pasang membuat direktori releases/<versi> berisi penanda versi.
func pasang(root, versi string) error {
	dir := filepath.Join(root, "releases", versi)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return err
	}
	penanda := "berkas ini menandai versi " + versi + "\n"
	return os.WriteFile(filepath.Join(dir, "VERSION"), []byte(penanda), 0o644)
}

// alihkan mengarahkan symlink current ke versi tertentu.
// Symlink sementara dibuat dulu, lalu diganti lewat rename yang bersifat atomik.
func alihkan(root, versi string) error {
	target := filepath.Join("releases", versi) // relatif agar pindah folder tetap valid
	link := filepath.Join(root, "current")
	sementara := link + "-baru"
	if err := os.Remove(sementara); err != nil && !os.IsNotExist(err) {
		return err
	}
	if err := os.Symlink(target, sementara); err != nil {
		return err
	}
	return os.Rename(sementara, link)
}

// versiAktif membaca versi yang ditunjuk symlink current.
func versiAktif(root string) (string, error) {
	target, err := filepath.EvalSymlinks(filepath.Join(root, "current"))
	if err != nil {
		return "", err
	}
	return filepath.Base(target), nil
}

// lapor mencetak keadaan current beserta isi berkas VERSION di dalamnya.
func lapor(root, kejadian string) {
	v, err := versiAktif(root)
	if err != nil {
		fmt.Println("gagal membaca current:", err)
		os.Exit(1)
	}
	isi, err := os.ReadFile(filepath.Join(root, "current", "VERSION"))
	if err != nil {
		fmt.Println("gagal membaca VERSION:", err)
		os.Exit(1)
	}
	fmt.Printf("%-20s current -> %s (VERSION: %s)\n", kejadian, v, strings.TrimSpace(string(isi)))
}

func main() {
	root, err := os.MkdirTemp("", "sapa-rilis-*")
	if err != nil {
		fmt.Println("gagal membuat direktori sementara:", err)
		os.Exit(1)
	}
	defer os.RemoveAll(root)

	// Dua rilis terpasang berdampingan; versi lama tidak dihapus.
	for _, v := range []string{"v1.4.1", "v1.4.2"} {
		if err := pasang(root, v); err != nil {
			fmt.Println("gagal memasang", v, ":", err)
			os.Exit(1)
		}
	}

	// Rilis normal: alihkan current ke versi terbaru.
	if err := alihkan(root, "v1.4.2"); err != nil {
		fmt.Println("gagal rilis:", err)
		os.Exit(1)
	}
	lapor(root, "setelah rilis")

	// Insiden: v1.4.2 bermasalah; rollback hanya mengarahkan ulang symlink.
	if err := alihkan(root, "v1.4.1"); err != nil {
		fmt.Println("gagal rollback:", err)
		os.Exit(1)
	}
	lapor(root, "setelah rollback")

	// Roll forward: perbaikan sudah dirilis ulang sebagai v1.4.2.
	if err := alihkan(root, "v1.4.2"); err != nil {
		fmt.Println("gagal roll forward:", err)
		os.Exit(1)
	}
	lapor(root, "setelah roll forward")
}
