package main

import (
	"fmt"
	"net"
	"os"
	"strconv"
)

// cek menyimpan satu hasil pemeriksaan kesiapan container.
type cek struct {
	nama  string
	hasil string
	lulus bool
}

func main() {
	semua := []cek{
		cekAlamat(os.Getenv("APP_ADDR")),
		cekUser(),
		cekTerisi("APP_LOG_LEVEL", os.Getenv("APP_LOG_LEVEL")),
	}

	fmt.Println("preflight container:")
	gagal := 0
	for _, c := range semua {
		penanda := "[OK]"
		if !c.lulus {
			penanda = "[GAGAL]"
			gagal++
		}
		fmt.Printf("  %-8s %s: %s\n", penanda, c.nama, c.hasil)
	}
	if gagal > 0 {
		fmt.Printf("%d pemeriksaan gagal; aplikasi menolak start\n", gagal)
		os.Exit(1)
	}
	fmt.Println("semua pemeriksaan lulus; aplikasi siap menerima trafik")
}

// cekAlamat memastikan APP_ADDR bisa dijangkau dari luar container.
func cekAlamat(alamat string) cek {
	host, portStr, err := net.SplitHostPort(alamat)
	if err != nil {
		return cek{"APP_ADDR=" + alamat, "tidak bisa diurai: " + err.Error(), false}
	}
	if host == "127.0.0.1" || host == "localhost" {
		return cek{"APP_ADDR=" + alamat, "host loopback tidak terjangkau dari luar container", false}
	}
	port, err := strconv.Atoi(portStr)
	if err != nil || port < 1 {
		return cek{"APP_ADDR=" + alamat, "port tidak valid", false}
	}
	return cek{"APP_ADDR=" + alamat, "host " + host + ", port " + portStr, true}
}

// cekUser memastikan proses tidak berjalan sebagai root.
func cekUser() cek {
	uid := os.Getuid()
	if uid == 0 {
		return cek{"uid=" + fmt.Sprint(uid), "proses berjalan sebagai root", false}
	}
	return cek{"uid=" + fmt.Sprint(uid), "bukan root", true}
}

// cekTerisi memastikan variabel wajib memiliki nilai.
func cekTerisi(nama, nilai string) cek {
	if nilai == "" {
		return cek{nama, "kosong", false}
	}
	return cek{nama, "terisi (" + nilai + ")", true}
}
