awesome-cli/internal/handler/coffee_handler.go

132 lines
3.7 KiB
Go
Raw Normal View History

2025-10-16 14:54:24 +03:00
package handler
import (
"errors"
"fmt"
"strconv"
"awesome_cli/internal/service"
"awesome_cli/pkg/ui"
libErr "code.linberg.su/linberg/awesome-back/pkg/errors"
)
type CoffeeHandler struct {
coffeeService *service.CoffeeService
}
func NewCoffeeHandler(coffeeService *service.CoffeeService) *CoffeeHandler {
return &CoffeeHandler{
coffeeService: coffeeService,
}
}
func (h *CoffeeHandler) HandleList() error {
coffees, err := h.coffeeService.GetAllCoffees()
if err != nil {
return h.handleError(err, "Failed to list coffees")
}
h.printCoffeesTable(coffees)
return nil
}
func (h *CoffeeHandler) HandleGet(coffeeID string) error {
id, err := strconv.Atoi(coffeeID)
if err != nil {
return libErr.NewInvalidError("coffee ID must be a number")
}
coffee, err := h.coffeeService.GetCoffeeByID(id)
if err != nil {
return h.handleError(err, fmt.Sprintf("Failed to get coffee with ID %d", id))
}
h.printCoffeeDetail(coffee)
return nil
}
func (h *CoffeeHandler) HandleGetWithRetry(coffeeID string, maxRetries int) error {
id, err := strconv.Atoi(coffeeID)
if err != nil {
return libErr.NewInvalidError("coffee ID must be a number")
}
fmt.Printf("Fetching coffee with ID %d (max retries: %d)...\n", id, maxRetries)
coffee, err := h.coffeeService.GetCoffeeByIDWithRetry(id, maxRetries)
if err != nil {
return h.handleError(err, fmt.Sprintf("Failed to get coffee with ID %d after retries", id))
}
h.printCoffeeDetail(coffee)
return nil
}
func (h *CoffeeHandler) printCoffeesTable(coffees []service.Coffee) {
t := ui.NewTableBuilder()
t.AddTableHeader("ID", "Name", "Price", "Size", "Description")
for _, coffee := range coffees {
t.AddRow(
strconv.FormatInt(int64(coffee.ID), 10),
coffee.Name,
strconv.FormatInt(int64(coffee.Price), 10),
coffee.Size,
coffee.Description,
)
}
fmt.Println(t.CreateTable())
}
func (h *CoffeeHandler) printCoffeeDetail(coffee *service.Coffee) {
fmt.Printf("ID: %s\n", ui.SetColor(ui.Green, strconv.FormatInt(int64(coffee.ID), 10)))
fmt.Printf("Name: %s\n", ui.SetColor(ui.Green, coffee.Name))
fmt.Printf("Price: %s\n", ui.SetColor(ui.Green, fmt.Sprintf("%.2f ₽", coffee.Price)))
fmt.Printf("Size: %s\n", ui.SetColor(ui.Green, coffee.Size))
fmt.Printf("Description: %s\n", ui.SetColor(ui.Green, coffee.Description))
fmt.Println()
}
// handleError демонстрирует продвинутую обработку ошибок
func (h *CoffeeHandler) handleError(err error, message string) error {
red := func(s string) string {
return ui.SetColor(ui.Red, s)
}
fmt.Printf("%s: %s\n", red("Error"), message)
// Демонстрация использования errors.Is и errors.As
switch {
case libErr.IsNotFound(err):
fmt.Printf("%s: Resource not found\n", red("Type"))
fmt.Printf("%s: %v\n", red("Details"), err)
case libErr.IsInvalid(err):
fmt.Printf("%s: Invalid request\n", red("Type"))
fmt.Printf("%s: %v\n", red("Details"), err)
case libErr.IsNetworkError(err):
fmt.Printf("%s: Network error\n", red("Type"))
fmt.Printf("%s: Please check your connection and try again\n", red("Details"))
default:
// Используем errors.As для получения дополнительной информации
var appErr *libErr.AppError
if errors.As(err, &appErr) {
fmt.Printf("%s: %s\n", red("Type"), string(appErr.Type))
fmt.Printf("%s: %s\n", red("Message"), appErr.Message)
// Демонстрация unwrap цепочки ошибок
if appErr.Err != nil {
fmt.Printf("%s: %v\n", red("Underlying error"), appErr.Err)
}
} else {
fmt.Printf("%s: %v\n", red("Unknown error"), err)
}
}
fmt.Println() // Пустая строка для читабельности
return err
}