package service import ( "fmt" "log/slog" "github.com/rogeecn/database_render/internal/config" "github.com/rogeecn/database_render/internal/database" "github.com/rogeecn/database_render/internal/model" "github.com/rogeecn/database_render/internal/repository" ) // DataService handles business logic for data operations type DataService struct { repo *repository.DataRepository config *config.Config logger *slog.Logger } // NewDataService creates a new data service func NewDataService(repo *repository.DataRepository, cfg *config.Config) *DataService { return &DataService{ repo: repo, config: cfg, logger: slog.With("component", "service"), } } // GetTables returns all configured tables func (s *DataService) GetTables() ([]model.TableInfo, error) { tables, err := s.repo.GetTables() if err != nil { s.logger.Error("failed to get tables", "error", err) return nil, err } s.logger.Debug("retrieved tables", "count", len(tables)) return tables, nil } // GetTableData returns paginated data for a table func (s *DataService) GetTableData(tableName string, page, pageSize int, search string, sortField string, sortOrder string) (*model.DataResponse, error) { // Validate table exists tableConfig, err := s.repo.GetTableConfig(tableName) if err != nil { s.logger.Error("failed to get table config", "table", tableName, "error", err) return nil, err } // Use configured page size if not provided if pageSize <= 0 { pageSize = tableConfig.PageSize } // Validate page and page size if page <= 0 { page = 1 } if pageSize <= 0 { pageSize = 10 } if pageSize > 100 { pageSize = 100 // Limit maximum page size } // Get data from repository data, total, err := s.repo.GetTableData(tableName, page, pageSize, search, sortField, sortOrder) if err != nil { s.logger.Error("failed to get table data", "table", tableName, "page", page, "pageSize", pageSize, "search", search, "error", err) return nil, err } // Calculate total pages totalPages := int((total + int64(pageSize) - 1) / int64(pageSize)) response := &model.DataResponse{ Data: data, Total: total, Page: page, PerPage: pageSize, Pages: totalPages, Table: tableName, Columns: tableConfig.Columns, Filters: tableConfig.Filters, } s.logger.Info("retrieved table data", "table", tableName, "page", page, "pageSize", pageSize, "total", total, "pages", totalPages) return response, nil } // GetTableDetail returns a single record detail func (s *DataService) GetTableDetail(tableName string, id interface{}) (*model.DetailResponse, error) { // Validate table exists _, err := s.repo.GetTableConfig(tableName) if err != nil { s.logger.Error("failed to get table config", "table", tableName, "error", err) return nil, err } // Get data from repository data, err := s.repo.GetTableDataByID(tableName, id) if err != nil { s.logger.Error("failed to get table detail", "table", tableName, "id", id, "error", err) return nil, err } response := &model.DetailResponse{ Data: data, } s.logger.Debug("retrieved table detail", "table", tableName, "id", id) return response, nil } // GetTableColumns returns column information for a table func (s *DataService) GetTableColumns(tableName string) ([]database.ColumnInfo, error) { // Validate table exists _, err := s.repo.GetTableConfig(tableName) if err != nil { s.logger.Error("failed to get table config", "table", tableName, "error", err) return nil, err } // Get column information from repository columns, err := s.repo.GetTableColumns(tableName) if err != nil { s.logger.Error("failed to get table columns", "table", tableName, "error", err) return nil, err } return columns, nil } // ValidateConfiguration validates the entire configuration func (s *DataService) ValidateConfiguration() error { // Validate tables configuration if len(s.config.Tables) == 0 { return fmt.Errorf("no tables configured") } // Validate table existence in database if err := s.repo.ValidateTableConfig(); err != nil { return err } // Validate individual table configurations for tableName, tableConfig := range s.config.Tables { if tableConfig.Alias == "" { return fmt.Errorf("table %s has empty alias", tableName) } if tableConfig.PageSize <= 0 { return fmt.Errorf("table %s has invalid page size", tableName) } // Validate field configurations for fieldName, fieldConfig := range tableConfig.Fields { if fieldConfig.Type == "" { return fmt.Errorf("field %s in table %s has empty type", fieldName, tableName) } } } s.logger.Info("configuration validation completed successfully") return nil } // GetTableConfig returns the configuration for a specific table func (s *DataService) GetTableConfig(tableName string) (*model.TableConfig, error) { return s.repo.GetTableConfig(tableName) } // GetDefaultTable returns the first configured table name func (s *DataService) GetDefaultTable() (string, error) { if len(s.config.Tables) == 0 { return "", fmt.Errorf("no tables configured") } // Return the first table name for tableName := range s.config.Tables { return tableName, nil } return "", fmt.Errorf("no tables configured") }