package handler import ( "fmt" "log/slog" "net/http" "strconv" "github.com/gofiber/fiber/v3" "github.com/rogeecn/database_render/internal/service" ) // DataHandler handles HTTP requests for data operations type DataHandler struct { service *service.DataService logger *slog.Logger } // NewDataHandler creates a new data handler func NewDataHandler(service *service.DataService) *DataHandler { return &DataHandler{ service: service, logger: slog.With("component", "handler"), } } // GetTables returns all configured tables func (h *DataHandler) GetTables(c fiber.Ctx) error { tables, err := h.service.GetTables() if err != nil { h.logger.Error("failed to get tables", "error", err) return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "error": "Failed to get tables", }) } h.logger.Debug("retrieved tables", "count", len(tables)) return c.JSON(fiber.Map{ "tables": tables, }) } // GetTableData returns paginated data for a table func (h *DataHandler) GetTableData(c fiber.Ctx) error { tableName := c.Params("table") if tableName == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "error": "Table name is required", }) } // Parse query parameters page, err := strconv.Atoi(c.Query("page", "1")) if err != nil || page <= 0 { page = 1 } pageSize, err := strconv.Atoi(c.Query("per_page", "10")) if err != nil || pageSize <= 0 { pageSize = 10 } search := c.Query("search", "") sortField := c.Query("sort", "") sortOrder := c.Query("order", "asc") // Validate sort order if sortOrder != "asc" && sortOrder != "desc" { sortOrder = "asc" } // Get table data data, err := h.service.GetTableData(tableName, page, pageSize, search, sortField, sortOrder) if err != nil { h.logger.Error("failed to get table data", "table", tableName, "page", page, "error", err) return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "error": fmt.Sprintf("Failed to get table data: %v", err), }) } return c.JSON(data) } // GetTableDetail returns a single record detail func (h *DataHandler) GetTableDetail(c fiber.Ctx) error { tableName := c.Params("table") if tableName == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "error": "Table name is required", }) } id := c.Params("id") if id == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "error": "ID is required", }) } // Get table detail detail, err := h.service.GetTableDetail(tableName, id) if err != nil { h.logger.Error("failed to get table detail", "table", tableName, "id", id, "error", err) return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "error": fmt.Sprintf("Failed to get table detail: %v", err), }) } return c.JSON(detail) } // GetTableConfig returns the configuration for a specific table func (h *DataHandler) GetTableConfig(c fiber.Ctx) error { tableName := c.Params("table") if tableName == "" { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "error": "Table name is required", }) } config, err := h.service.GetTableConfig(tableName) if err != nil { h.logger.Error("failed to get table config", "table", tableName, "error", err) return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "error": fmt.Sprintf("Failed to get table config: %v", err), }) } return c.JSON(config) } // Health returns the health status func (h *DataHandler) Health(c fiber.Ctx) error { return c.JSON(fiber.Map{ "status": "ok", "message": "Service is healthy", }) } // SetupRoutes sets up all the routes for the data handler func (h *DataHandler) SetupRoutes(app *fiber.App) { // API routes api := app.Group("/api") // Table routes api.Get("/tables", h.GetTables) api.Get("/data/:table", h.GetTableData) api.Get("/data/:table/detail/:id", h.GetTableDetail) api.Get("/config/:table", h.GetTableConfig) // Health check api.Get("/health", h.Health) }