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

package {{ package_name }}

import (
{% if has_request_body %}
	"bytes"
{% endif %}
	"context"
	"encoding/json"
	"fmt"
	"io"
{% if has_multipart %}
	"mime/multipart"
{% endif %}
	"net/http"
{% if has_query_params %}
	"net/url"
{% endif %}
{% if has_path_params %}
	"strings"
{% endif %}

	// Import shared package for error types
	"{{ module_name }}/shared"
)

// Client provides access to {{ package_name }} operations.
type Client struct {
	BaseURL    string
	HTTPClient *http.Client
	Token      string
}

// NewClient creates a new {{ package_name }} client.
func NewClient(baseURL string, httpClient *http.Client, token string) *Client {
	return &Client{
		BaseURL:    baseURL,
		HTTPClient: httpClient,
		Token:      token,
	}
}

{% for operation in operations %}
{% if operation.query_params_struct %}
// {{ operation.query_params_struct.name }} contains query parameters for {{ operation.name }}.
type {{ operation.query_params_struct.name }} struct {
{% for field in operation.query_params_struct.fields %}
	{{ field.name }} {{ field.type }} `json:"{{ field.json_name }}"`
{% endfor %}
}

{% endif %}
{% endfor %}

{% for operation in operations %}
// {{ operation.name }} - {{ operation.description | replace('\n', '\n// ') }}
func (c *Client) {{ operation.name }}(ctx context.Context{% for param in operation.parameters %}, {{ param.name }} {{ param.type }}{% endfor %}{% if operation.request_type %}, body {{ operation.request_type }}{% endif %}) ({{ operation.response_type }}, error) {
	var result {{ operation.response_type }}

	// Build URL
	path := "{{ operation.path }}"
{% for param in operation.parameters %}
{% if param.location == "path" %}
	path = strings.ReplaceAll(path, "{{ '{' }}{{ param.name }}{{ '}' }}", fmt.Sprintf("%v", {{ param.name }}))
{% endif %}
{% endfor %}

{% if operation.parameters|selectattr("location", "equalto", "query")|list %}
	// Add query parameters
	if params != nil {
		query := url.Values{}
		// TODO: Add query parameter marshaling based on struct fields
		path = path + "?" + query.Encode()
	}
{% endif %}

	u := c.BaseURL + path

{% if operation.is_multipart and operation.multipart_fields %}
	// Build multipart form data
	var buf bytes.Buffer
	writer := multipart.NewWriter(&buf)

{% for field in operation.multipart_fields.file_fields %}
	// Add file field: {{ field.name }}
	if body.{{ field.go_name }} != nil {
		part, err := writer.CreateFormFile("{{ field.name }}", "{{ field.name }}")
		if err != nil {
			return result, fmt.Errorf("failed to create form file for {{ field.name }}: %w", err)
		}
		if _, err := io.Copy(part, body.{{ field.go_name }}); err != nil {
			return result, fmt.Errorf("failed to write file {{ field.name }}: %w", err)
		}
	}
{% endfor %}

{% for field in operation.multipart_fields.data_fields %}
	// Add form field: {{ field.name }}
{% if field.type == "map[string]interface{}" %}
	if body.{{ field.go_name }} != nil {
		metaBytes, err := json.Marshal(body.{{ field.go_name }})
		if err == nil {
			if err := writer.WriteField("{{ field.name }}", string(metaBytes)); err != nil {
				return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
			}
		}
	}
{% elif field.is_array %}
	if len(body.{{ field.go_name }}) > 0 {
		arrBytes, err := json.Marshal(body.{{ field.go_name }})
		if err == nil {
			if err := writer.WriteField("{{ field.name }}", string(arrBytes)); err != nil {
				return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
			}
		}
	}
{% elif field.is_enum %}
	if body.{{ field.go_name }} != nil {
		if err := writer.WriteField("{{ field.name }}", string(*body.{{ field.go_name }})); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% elif not field.required %}
{% if field.type == "*string" %}
	if body.{{ field.go_name }} != nil && *body.{{ field.go_name }} != "" {
		if err := writer.WriteField("{{ field.name }}", *body.{{ field.go_name }}); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% elif field.type == "*bool" %}
	if body.{{ field.go_name }} != nil {
		if err := writer.WriteField("{{ field.name }}", fmt.Sprintf("%t", *body.{{ field.go_name }})); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% elif field.type == "*int64" or field.type == "*float64" %}
	if body.{{ field.go_name }} != nil {
		if err := writer.WriteField("{{ field.name }}", fmt.Sprintf("%v", *body.{{ field.go_name }})); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% else %}
	if body.{{ field.go_name }} != nil {
		if err := writer.WriteField("{{ field.name }}", fmt.Sprintf("%v", body.{{ field.go_name }})); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% endif %}
{% else %}
{% if field.type == "string" %}
	if body.{{ field.go_name }} != "" {
		if err := writer.WriteField("{{ field.name }}", body.{{ field.go_name }}); err != nil {
			return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
		}
	}
{% elif field.type == "bool" %}
	if err := writer.WriteField("{{ field.name }}", fmt.Sprintf("%t", body.{{ field.go_name }})); err != nil {
		return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
	}
{% else %}
	if err := writer.WriteField("{{ field.name }}", fmt.Sprintf("%v", body.{{ field.go_name }})); err != nil {
		return result, fmt.Errorf("failed to write field {{ field.name }}: %w", err)
	}
{% endif %}
{% endif %}
{% endfor %}

	if err := writer.Close(); err != nil {
		return result, fmt.Errorf("failed to close multipart writer: %w", err)
	}

	// Create request with multipart body
	req, err := http.NewRequestWithContext(ctx, "{{ operation.http_method }}", u, &buf)
	if err != nil {
		return result, fmt.Errorf("failed to create request: %w", err)
	}

	// Set multipart content type with boundary
	req.Header.Set("Content-Type", writer.FormDataContentType())
{% elif operation.request_type %}
	// Prepare JSON request body
	var reqBody io.Reader
	bodyBytes, err := json.Marshal(body)
	if err != nil {
		return result, fmt.Errorf("failed to marshal request body: %w", err)
	}
	reqBody = bytes.NewReader(bodyBytes)

	// Create request
	req, err := http.NewRequestWithContext(ctx, "{{ operation.http_method }}", u, reqBody)
	if err != nil {
		return result, fmt.Errorf("failed to create request: %w", err)
	}

	// Set JSON content type
	req.Header.Set("Content-Type", "application/json")
{% else %}
	// Create request without body
	req, err := http.NewRequestWithContext(ctx, "{{ operation.http_method }}", u, nil)
	if err != nil {
		return result, fmt.Errorf("failed to create request: %w", err)
	}
{% endif %}

	// Set authorization header
	if c.Token != "" {
		req.Header.Set("Authorization", "Bearer "+c.Token)
	}

	// Execute request
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return result, &shared.NetworkError{
			Err:    err,
			Method: "{{ operation.http_method }}",
			URL:    u,
		}
	}
	defer resp.Body.Close()

	// Read response body
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return result, &shared.NetworkError{
			Err:    fmt.Errorf("failed to read response: %w", err),
			Method: "{{ operation.http_method }}",
			URL:    u,
		}
	}

	// Check status code
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return result, shared.ParseAPIError(resp.StatusCode, resp.Status, "{{ operation.http_method }}", u, respBody)
	}

{% if operation.http_method != "DELETE" %}
	// Decode response
	if err := json.Unmarshal(respBody, &result); err != nil {
		return result, &shared.UnmarshalError{
			Err:  err,
			Body: respBody,
			Type: "{{ operation.response_type }}",
		}
	}
{% endif %}

	return result, nil
}

{% endfor %}
