package content import ( "context" "database/sql" "fmt" "time" "github.com/insertr/insertr/internal/db" "github.com/insertr/insertr/internal/db/postgresql" "github.com/insertr/insertr/internal/db/sqlite" ) // DatabaseClient implements ContentClient for direct database access type DatabaseClient struct { db *db.Database } // NewDatabaseClient creates a new database content client func NewDatabaseClient(database *db.Database) *DatabaseClient { return &DatabaseClient{ db: database, } } // GetContent fetches a single content item by ID func (d *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, error) { ctx := context.Background() var content interface{} var err error switch d.db.GetDBType() { case "sqlite3": content, err = d.db.GetSQLiteQueries().GetContent(ctx, sqlite.GetContentParams{ ID: contentID, SiteID: siteID, }) case "postgresql": content, err = d.db.GetPostgreSQLQueries().GetContent(ctx, postgresql.GetContentParams{ ID: contentID, SiteID: siteID, }) default: return nil, fmt.Errorf("unsupported database type: %s", d.db.GetDBType()) } if err != nil { if err == sql.ErrNoRows { return nil, nil // Content not found, return nil without error } return nil, fmt.Errorf("database error: %w", err) } item := d.convertToContentItem(content) return &item, nil } // GetBulkContent fetches multiple content items by IDs func (d *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map[string]ContentItem, error) { if len(contentIDs) == 0 { return make(map[string]ContentItem), nil } ctx := context.Background() var dbContent interface{} var err error switch d.db.GetDBType() { case "sqlite3": dbContent, err = d.db.GetSQLiteQueries().GetBulkContent(ctx, sqlite.GetBulkContentParams{ SiteID: siteID, Ids: contentIDs, }) case "postgresql": dbContent, err = d.db.GetPostgreSQLQueries().GetBulkContent(ctx, postgresql.GetBulkContentParams{ SiteID: siteID, Ids: contentIDs, }) default: return nil, fmt.Errorf("unsupported database type: %s", d.db.GetDBType()) } if err != nil { return nil, fmt.Errorf("database error: %w", err) } items := d.convertToContentItemList(dbContent) // Convert slice to map for easy lookup result := make(map[string]ContentItem) for _, item := range items { result[item.ID] = item } return result, nil } // GetAllContent fetches all content for a site func (d *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, error) { ctx := context.Background() var dbContent interface{} var err error switch d.db.GetDBType() { case "sqlite3": dbContent, err = d.db.GetSQLiteQueries().GetAllContent(ctx, siteID) case "postgresql": dbContent, err = d.db.GetPostgreSQLQueries().GetAllContent(ctx, siteID) default: return nil, fmt.Errorf("unsupported database type: %s", d.db.GetDBType()) } if err != nil { return nil, fmt.Errorf("database error: %w", err) } items := d.convertToContentItemList(dbContent) // Convert slice to map for easy lookup result := make(map[string]ContentItem) for _, item := range items { result[item.ID] = item } return result, nil } // convertToContentItem converts database models to content.ContentItem func (d *DatabaseClient) convertToContentItem(content interface{}) ContentItem { switch d.db.GetDBType() { case "sqlite3": c := content.(sqlite.Content) return ContentItem{ ID: c.ID, SiteID: c.SiteID, Value: c.Value, Type: c.Type, UpdatedAt: time.Unix(c.UpdatedAt, 0).Format(time.RFC3339), } case "postgresql": c := content.(postgresql.Content) return ContentItem{ ID: c.ID, SiteID: c.SiteID, Value: c.Value, Type: c.Type, UpdatedAt: time.Unix(c.UpdatedAt, 0).Format(time.RFC3339), } } return ContentItem{} // Should never happen } // convertToContentItemList converts database model lists to content.ContentItem slice func (d *DatabaseClient) convertToContentItemList(contentList interface{}) []ContentItem { switch d.db.GetDBType() { case "sqlite3": list := contentList.([]sqlite.Content) items := make([]ContentItem, len(list)) for i, content := range list { items[i] = d.convertToContentItem(content) } return items case "postgresql": list := contentList.([]postgresql.Content) items := make([]ContentItem, len(list)) for i, content := range list { items[i] = d.convertToContentItem(content) } return items } return []ContentItem{} // Should never happen }