package tui import ( "bytes" "encoding/json" "fmt" "io" "net/http" "time" ) // APIClient provides a client for interacting with the Atlas API type APIClient struct { baseURL string httpClient *http.Client token string } // NewAPIClient creates a new API client func NewAPIClient(baseURL string) *APIClient { return &APIClient{ baseURL: baseURL, httpClient: &http.Client{ Timeout: 30 * time.Second, }, } } // SetToken sets the authentication token func (c *APIClient) SetToken(token string) { c.token = token } // Login authenticates with the API func (c *APIClient) Login(username, password string) (string, error) { reqBody := map[string]string{ "username": username, "password": password, } body, err := json.Marshal(reqBody) if err != nil { return "", err } req, err := http.NewRequest("POST", c.baseURL+"/api/v1/auth/login", bytes.NewReader(body)) if err != nil { return "", err } req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return "", fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return "", fmt.Errorf("login failed: %s", string(body)) } var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return "", err } token, ok := result["token"].(string) if !ok { return "", fmt.Errorf("no token in response") } c.SetToken(token) return token, nil } // Get performs a GET request func (c *APIClient) Get(path string) ([]byte, error) { req, err := http.NewRequest("GET", c.baseURL+path, nil) if err != nil { return nil, err } if c.token != "" { req.Header.Set("Authorization", "Bearer "+c.token) } resp, err := c.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode >= 400 { return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body)) } return body, nil } // Post performs a POST request func (c *APIClient) Post(path string, data interface{}) ([]byte, error) { body, err := json.Marshal(data) if err != nil { return nil, err } req, err := http.NewRequest("POST", c.baseURL+path, bytes.NewReader(body)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") if c.token != "" { req.Header.Set("Authorization", "Bearer "+c.token) } resp, err := c.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode >= 400 { return nil, fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(respBody)) } return respBody, nil } // Delete performs a DELETE request func (c *APIClient) Delete(path string) error { req, err := http.NewRequest("DELETE", c.baseURL+path, nil) if err != nil { return err } if c.token != "" { req.Header.Set("Authorization", "Bearer "+c.token) } resp, err := c.httpClient.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode >= 400 { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("API error (status %d): %s", resp.StatusCode, string(body)) } return nil }