package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"
)

// aturCookie menulis empat cookie dengan konfigurasi berbeda ke respons.
func aturCookie(w http.ResponseWriter, r *http.Request) {
	// Cookie sesi: tanpa MaxAge/Expires, hilang saat browser ditutup.
	http.SetCookie(w, &http.Cookie{
		Name:     "sesi",
		Value:    "sesi-budi-aktif",
		Path:     "/",
		HttpOnly: true,
		SameSite: http.SameSiteLaxMode,
	})
	// Cookie persisten: bertahan 3600 detik di penyimpanan browser.
	http.SetCookie(w, &http.Cookie{
		Name:   "preferensi",
		Value:  "tema-gelap",
		Path:   "/",
		MaxAge: 3600,
	})
	// Prefix __Host-: wajib Secure, Path=/, tanpa Domain.
	http.SetCookie(w, &http.Cookie{
		Name:   "__Host-tema",
		Value:  "biru",
		Path:   "/",
		Secure: true,
	})
	// Cookie dengan batas waktu absolut lewat Expires.
	http.SetCookie(w, &http.Cookie{
		Name:    "kupon",
		Value:   "DISKON20",
		Path:    "/",
		Expires: time.Date(2026, 1, 16, 8, 0, 0, 0, time.UTC),
	})
}

func bacaCookie(w http.ResponseWriter, r *http.Request) {
	c, err := r.Cookie("sesi")
	if err != nil {
		http.Error(w, "cookie sesi tidak ditemukan", http.StatusBadRequest)
		return
	}
	fmt.Fprintf(w, "nilai cookie sesi: %s", c.Value)
}

func namaSameSite(s http.SameSite) string {
	switch s {
	case http.SameSiteLaxMode:
		return "Lax"
	case http.SameSiteStrictMode:
		return "Strict"
	case http.SameSiteNoneMode:
		return "None"
	default:
		return "default"
	}
}

func deskripsi(c *http.Cookie) string {
	maxAge := fmt.Sprintf("%d", c.MaxAge)
	if c.MaxAge == 0 {
		maxAge = "0 (cookie sesi)"
	}
	expires := c.Expires.Format("2006-01-02 15:04 MST")
	if c.Expires.IsZero() {
		expires = "tidak diset"
	}
	return fmt.Sprintf("HttpOnly=%-5v Secure=%-5v SameSite=%-7s Path=%s MaxAge=%s Expires=%s",
		c.HttpOnly, c.Secure, namaSameSite(c.SameSite), c.Path, maxAge, expires)
}

func main() {
	// Permintaan pertama: server mengatur empat cookie sekaligus.
	req := httptest.NewRequest("GET", "/masuk", nil)
	rec := httptest.NewRecorder()
	aturCookie(rec, req)
	resp := rec.Result()

	fmt.Println("header Set-Cookie mentah dari respons:")
	for _, v := range resp.Header["Set-Cookie"] {
		fmt.Println("  " + v)
	}

	// Parsing kembali atribut setiap cookie dari respons yang sama.
	fmt.Println()
	fmt.Println("atribut hasil parsing setiap cookie:")
	cookies := resp.Cookies()
	for _, c := range cookies {
		fmt.Printf("  %-12s %s\n", c.Name, deskripsi(c))
	}

	// Kunjungan kedua: browser mengirim semua cookie kembali ke server.
	fmt.Println()
	fmt.Println("kunjungan kedua, cookie yang terkirim balik:")
	reqKedua := httptest.NewRequest("GET", "/baca", nil)
	for _, c := range cookies {
		fmt.Printf("  %-12s = %s\n", c.Name, c.Value)
		reqKedua.AddCookie(c)
	}

	recKedua := httptest.NewRecorder()
	bacaCookie(recKedua, reqKedua)
	fmt.Println()
	fmt.Println("handler /baca membalas :", recKedua.Body.String())
}
