// Code generated by django-cfg/django_client - DO NOT EDIT.
// Generated at: {{ generated_at }}

package {{ package_name }}

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// APIError represents an API error response with full context.
type APIError struct {
	// HTTP status code (e.g., 404, 500)
	StatusCode int `json:"status_code"`

	// HTTP status text (e.g., "Not Found")
	Status string `json:"status"`

	// Error message from API
	Message string `json:"message"`

	// Detailed error information (can be string, object, or array)
	Detail interface{} `json:"detail,omitempty"`

	// Field-specific validation errors
	Errors map[string]interface{} `json:"errors,omitempty"`

	// Raw response body
	Body []byte `json:"-"`

	// Request method (GET, POST, etc.)
	Method string `json:"method"`

	// Request URL
	URL string `json:"url"`
}

// Error implements the error interface.
func (e *APIError) Error() string {
	if e.Detail != nil {
		return fmt.Sprintf("API error: %s %s -> %d %s: %s (detail: %v)",
			e.Method, e.URL, e.StatusCode, e.Status, e.Message, e.Detail)
	}
	if e.Message != "" {
		return fmt.Sprintf("API error: %s %s -> %d %s: %s",
			e.Method, e.URL, e.StatusCode, e.Status, e.Message)
	}
	return fmt.Sprintf("API error: %s %s -> %d %s",
		e.Method, e.URL, e.StatusCode, e.Status)
}

// IsNotFound returns true if the error is a 404 Not Found.
func (e *APIError) IsNotFound() bool {
	return e.StatusCode == http.StatusNotFound
}

// IsUnauthorized returns true if the error is a 401 Unauthorized.
func (e *APIError) IsUnauthorized() bool {
	return e.StatusCode == http.StatusUnauthorized
}

// IsForbidden returns true if the error is a 403 Forbidden.
func (e *APIError) IsForbidden() bool {
	return e.StatusCode == http.StatusForbidden
}

// IsBadRequest returns true if the error is a 400 Bad Request.
func (e *APIError) IsBadRequest() bool {
	return e.StatusCode == http.StatusBadRequest
}

// IsValidationError returns true if the error is a 422 Unprocessable Entity (validation error).
func (e *APIError) IsValidationError() bool {
	return e.StatusCode == http.StatusUnprocessableEntity
}

// IsServerError returns true if the error is a 5xx server error.
func (e *APIError) IsServerError() bool {
	return e.StatusCode >= 500 && e.StatusCode < 600
}

// IsClientError returns true if the error is a 4xx client error.
func (e *APIError) IsClientError() bool {
	return e.StatusCode >= 400 && e.StatusCode < 500
}

// GetFieldError returns the error message for a specific field, if any.
func (e *APIError) GetFieldError(field string) (string, bool) {
	if e.Errors == nil {
		return "", false
	}
	if err, ok := e.Errors[field]; ok {
		return fmt.Sprintf("%v", err), true
	}
	return "", false
}

// HasFieldErrors returns true if there are field-specific validation errors.
func (e *APIError) HasFieldErrors() bool {
	return len(e.Errors) > 0
}

// ParseAPIError attempts to parse an error response from the API.
func ParseAPIError(statusCode int, status, method, url string, body []byte) error {
	apiErr := &APIError{
		StatusCode: statusCode,
		Status:     status,
		Method:     method,
		URL:        url,
		Body:       body,
	}

	// Try to parse JSON error response
	var errorResponse struct {
		Message string                 `json:"message"`
		Detail  interface{}            `json:"detail"`
		Errors  map[string]interface{} `json:"errors"`
		Error   string                 `json:"error"`
	}

	if err := json.Unmarshal(body, &errorResponse); err == nil {
		// Use message field if available
		if errorResponse.Message != "" {
			apiErr.Message = errorResponse.Message
		} else if errorResponse.Error != "" {
			apiErr.Message = errorResponse.Error
		}

		apiErr.Detail = errorResponse.Detail
		apiErr.Errors = errorResponse.Errors
	} else {
		// If JSON parsing fails, use body as message
		apiErr.Message = string(body)
	}

	return apiErr
}

// NetworkError represents a network-level error (connection failed, timeout, etc.).
type NetworkError struct {
	// Underlying error
	Err error

	// Request method
	Method string

	// Request URL
	URL string
}

// Error implements the error interface.
func (e *NetworkError) Error() string {
	return fmt.Sprintf("network error: %s %s: %v", e.Method, e.URL, e.Err)
}

// Unwrap returns the underlying error.
func (e *NetworkError) Unwrap() error {
	return e.Err
}

// UnmarshalError represents an error unmarshaling the response.
type UnmarshalError struct {
	// Underlying error
	Err error

	// Response body
	Body []byte

	// Expected type
	Type string
}

// Error implements the error interface.
func (e *UnmarshalError) Error() string {
	return fmt.Sprintf("failed to unmarshal response into %s: %v (body: %s)", e.Type, e.Err, string(e.Body))
}

// Unwrap returns the underlying error.
func (e *UnmarshalError) Unwrap() error {
	return e.Err
}
