package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/jarcoal/httpmock"
)

// API response types
type User struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

type APIError struct {
	Message string `json:"message"`
	Code    int    `json:"code"`
}

func main() {
	// Activate httpmock
	httpmock.Activate()
	defer httpmock.DeactivateAndReset()

	// Register a simple responder
	httpmock.RegisterResponder("GET", "https://api.example.com/users/1",
		httpmock.NewStringResponder(200, `{"id": 1, "name": "Alice", "email": "alice@example.com"}`))

	// Make request using standard http client
	resp, err := http.Get("https://api.example.com/users/1")
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	var user User
	json.NewDecoder(resp.Body).Decode(&user)
	fmt.Printf("User: %+v\n", user)

	// Register JSON responder (auto-marshals)
	httpmock.RegisterResponder("GET", "https://api.example.com/users/2",
		httpmock.NewJsonResponderOrPanic(200, User{
			ID: 2, Name: "Bob", Email: "bob@example.com",
		}))

	resp, _ = http.Get("https://api.example.com/users/2")
	defer resp.Body.Close()
	json.NewDecoder(resp.Body).Decode(&user)
	fmt.Printf("User 2: %+v\n", user)

	// Match any URL with regex
	httpmock.RegisterResponder("GET", `=~^https://api\.example\.com/users/\d+$`,
		httpmock.NewJsonResponderOrPanic(200, User{ID: 99, Name: "Generic", Email: "user@example.com"}))

	resp, _ = http.Get("https://api.example.com/users/999")
	defer resp.Body.Close()
	json.NewDecoder(resp.Body).Decode(&user)
	fmt.Printf("User 999: %+v\n", user)

	// Dynamic responder with request inspection
	httpmock.RegisterResponder("POST", "https://api.example.com/users",
		func(req *http.Request) (*http.Response, error) {
			body, _ := io.ReadAll(req.Body)
			var newUser User
			json.Unmarshal(body, &newUser)

			// Return created user with ID
			newUser.ID = 100
			return httpmock.NewJsonResponse(201, newUser)
		})

	reqBody := strings.NewReader(`{"name": "Charlie", "email": "charlie@example.com"}`)
	resp, _ = http.Post("https://api.example.com/users", "application/json", reqBody)
	defer resp.Body.Close()
	json.NewDecoder(resp.Body).Decode(&user)
	fmt.Printf("Created: %+v\n", user)

	// Simulate errors
	httpmock.RegisterResponder("GET", "https://api.example.com/error",
		httpmock.NewJsonResponderOrPanic(500, APIError{
			Message: "Internal server error",
			Code:    500,
		}))

	// Simulate connection error
	httpmock.RegisterResponder("GET", "https://api.example.com/timeout",
		httpmock.NewErrorResponder(fmt.Errorf("connection timeout")))

	// Check call count
	info := httpmock.GetCallCountInfo()
	fmt.Println("\nCall counts:")
	for endpoint, count := range info {
		fmt.Printf("  %s: %d calls\n", endpoint, count)
	}

	// Reset for next test
	httpmock.Reset()
}
