package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"time"
)

func main() {
	// Server uji lokal dari net/http/httptest berperan sebagai server jauh.
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch r.URL.Path {
		case "/halo":
			fmt.Fprintln(w, "Halo dari server lokal")
		case "/simpan":
			w.Header().Set("X-Request-Id", "req-001")
			w.WriteHeader(http.StatusCreated)
			fmt.Fprintln(w, `{"id":7,"pesan":"item tersimpan"}`)
		case "/lambat":
			time.Sleep(200 * time.Millisecond)
			fmt.Fprintln(w, "akhirnya sampai")
		}
	}))
	defer ts.Close()

	// Bagian 1: cara singkat memakai http.Get (memakai DefaultClient).
	resp, err := http.Get(ts.URL + "/halo")
	if err != nil {
		fmt.Println("gagal:", err)
		return
	}
	body, _ := io.ReadAll(resp.Body)
	resp.Body.Close()
	fmt.Printf("GET /halo -> %s\n", resp.Status)
	fmt.Printf("body      : %s", body)

	// Bagian 2: satu http.Client dipakai ulang + header custom.
	client := &http.Client{Timeout: 2 * time.Second}
	req, err := http.NewRequest(http.MethodPost, ts.URL+"/simpan",
		strings.NewReader(`{"nama":"Buku Go"}`))
	if err != nil {
		fmt.Println("gagal membuat request:", err)
		return
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer token-demo")

	resp2, err := client.Do(req)
	if err != nil {
		fmt.Println("gagal:", err)
		return
	}
	body2, _ := io.ReadAll(resp2.Body)
	resp2.Body.Close()
	fmt.Printf("POST /simpan -> %s\n", resp2.Status)
	fmt.Printf("body         : %s", body2)
	fmt.Printf("X-Request-Id : %s\n", resp2.Header.Get("X-Request-Id"))

	// Bagian 3: server tidur 200 ms, client hanya menunggu 50 ms.
	clientCepat := &http.Client{Timeout: 50 * time.Millisecond}
	_, err = clientCepat.Get(ts.URL + "/lambat")
	var urlErr *url.Error
	if errors.As(err, &urlErr) {
		fmt.Println("GET /lambat (Timeout 50 ms) -> gagal")
		fmt.Println("sebab        :", urlErr.Err)
		fmt.Println("DeadlineExceeded:", errors.Is(err, context.DeadlineExceeded))
	}
}
