package familyHub import ( "FamilyHub/src/config" "FamilyHub/src/domain" "bytes" "context" "encoding/json" "errors" "fmt" "net/http" "strconv" "time" ) var errUserNotFound = errors.New("user not found") func NewApiClient(config config.Config) (*HTTPClient, error) { return &HTTPClient{ config: config, client: &http.Client{ Timeout: 60 * time.Second, }, }, nil } func (c *HTTPClient) SendReceipt(ctx context.Context, payload domain.AddReceiptRequest) error { requestBody := map[string]any{ "receipt_number": payload.Number, "receipt_date": payload.Date, } if payload.FamilyID != nil { requestBody["family_id"] = *payload.FamilyID } if payload.CreatedBy != nil { requestBody["created_by"] = *payload.CreatedBy } if payload.Type != nil { requestBody["type"] = *payload.Type } if payload.Category != nil { requestBody["category"] = *payload.Category } if payload.Description != nil { requestBody["description"] = *payload.Description } body, err := json.Marshal(requestBody) if err != nil { return err } req, err := http.NewRequestWithContext( ctx, http.MethodPost, c.config.APIHost+c.config.APIPort+"/api/v1/transactions", bytes.NewReader(body), ) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 300 { return fmt.Errorf("api error: status %d", resp.StatusCode) } return nil } func (c *HTTPClient) EnsureUser(ctx context.Context, payload domain.CreateUserRequest) error { registered, err := c.IsUserRegistered(ctx, payload.TelegramID) if err != nil { return err } if registered { return nil } return c.RegisterUser(ctx, payload) } func (c *HTTPClient) IsUserRegistered(ctx context.Context, telegramID int64) (bool, error) { _, err := c.GetUserByTelegramID(ctx, telegramID) if err == nil { return true, nil } if errors.Is(err, errUserNotFound) { return false, nil } return false, err } func (c *HTTPClient) RegisterUser(ctx context.Context, payload domain.CreateUserRequest) error { body, err := json.Marshal(payload) if err != nil { return err } req, err := http.NewRequestWithContext( ctx, http.MethodPost, c.config.APIHost+c.config.APIPort+"/api/v1/users", bytes.NewReader(body), ) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 300 { return fmt.Errorf("api error: status %d", resp.StatusCode) } return nil } func (c *HTTPClient) GetUserByTelegramID(ctx context.Context, telegramID int64) (*domain.UserResponse, error) { req, err := http.NewRequestWithContext( ctx, http.MethodGet, c.config.APIHost+c.config.APIPort+"/api/v1/users/by-telegram/"+strconv.FormatInt(telegramID, 10), nil, ) if err != nil { return nil, err } resp, err := c.client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { return nil, errUserNotFound } if resp.StatusCode >= 300 { return nil, fmt.Errorf("api error: status %d", resp.StatusCode) } var user domain.UserResponse if err := json.NewDecoder(resp.Body).Decode(&user); err != nil { return nil, err } return &user, nil } func (c *HTTPClient) CreateFamily(ctx context.Context, payload domain.CreateFamilyRequest) error { body, err := json.Marshal(payload) if err != nil { return err } req, err := http.NewRequestWithContext( ctx, http.MethodPost, c.config.APIHost+c.config.APIPort+"/api/v1/families", bytes.NewReader(body), ) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 300 { return fmt.Errorf("api error: status %d", resp.StatusCode) } return nil }