package engine

import (
	"context"
	"fmt"

	"github.com/insertr/insertr/internal/db"
	"github.com/insertr/insertr/internal/db/postgresql"
	"github.com/insertr/insertr/internal/db/sqlite"
)

// DatabaseClient implements ContentClient interface using the database
type DatabaseClient struct {
	database *db.Database
}

// NewDatabaseClient creates a new database client
func NewDatabaseClient(database *db.Database) *DatabaseClient {
	return &DatabaseClient{
		database: database,
	}
}

// GetContent retrieves a single content item
func (c *DatabaseClient) GetContent(siteID, contentID string) (*ContentItem, error) {
	switch c.database.GetDBType() {
	case "sqlite3":
		content, err := c.database.GetSQLiteQueries().GetContent(context.Background(), sqlite.GetContentParams{
			ID:     contentID,
			SiteID: siteID,
		})
		if err != nil {
			return nil, err
		}
		return &ContentItem{
			ID:           content.ID,
			SiteID:       content.SiteID,
			Value:        content.Value,
			Type:         content.Type,
			LastEditedBy: content.LastEditedBy,
		}, nil

	case "postgresql":
		content, err := c.database.GetPostgreSQLQueries().GetContent(context.Background(), postgresql.GetContentParams{
			ID:     contentID,
			SiteID: siteID,
		})
		if err != nil {
			return nil, err
		}
		return &ContentItem{
			ID:           content.ID,
			SiteID:       content.SiteID,
			Value:        content.Value,
			Type:         content.Type,
			LastEditedBy: content.LastEditedBy,
		}, nil

	default:
		return nil, fmt.Errorf("unsupported database type: %s", c.database.GetDBType())
	}
}

// GetBulkContent retrieves multiple content items
func (c *DatabaseClient) GetBulkContent(siteID string, contentIDs []string) (map[string]ContentItem, error) {
	switch c.database.GetDBType() {
	case "sqlite3":
		contents, err := c.database.GetSQLiteQueries().GetBulkContent(context.Background(), sqlite.GetBulkContentParams{
			SiteID: siteID,
			Ids:    contentIDs,
		})
		if err != nil {
			return nil, err
		}

		items := make(map[string]ContentItem)
		for _, content := range contents {
			items[content.ID] = ContentItem{
				ID:           content.ID,
				SiteID:       content.SiteID,
				Value:        content.Value,
				Type:         content.Type,
				LastEditedBy: content.LastEditedBy,
			}
		}
		return items, nil

	case "postgresql":
		contents, err := c.database.GetPostgreSQLQueries().GetBulkContent(context.Background(), postgresql.GetBulkContentParams{
			SiteID: siteID,
			Ids:    contentIDs,
		})
		if err != nil {
			return nil, err
		}

		items := make(map[string]ContentItem)
		for _, content := range contents {
			items[content.ID] = ContentItem{
				ID:           content.ID,
				SiteID:       content.SiteID,
				Value:        content.Value,
				Type:         content.Type,
				LastEditedBy: content.LastEditedBy,
			}
		}
		return items, nil

	default:
		return nil, fmt.Errorf("unsupported database type: %s", c.database.GetDBType())
	}
}

// GetAllContent retrieves all content items for a site
func (c *DatabaseClient) GetAllContent(siteID string) (map[string]ContentItem, error) {
	switch c.database.GetDBType() {
	case "sqlite3":
		contents, err := c.database.GetSQLiteQueries().GetAllContent(context.Background(), siteID)
		if err != nil {
			return nil, err
		}

		items := make(map[string]ContentItem)
		for _, content := range contents {
			items[content.ID] = ContentItem{
				ID:           content.ID,
				SiteID:       content.SiteID,
				Value:        content.Value,
				Type:         content.Type,
				LastEditedBy: content.LastEditedBy,
			}
		}
		return items, nil

	case "postgresql":
		contents, err := c.database.GetPostgreSQLQueries().GetAllContent(context.Background(), siteID)
		if err != nil {
			return nil, err
		}

		items := make(map[string]ContentItem)
		for _, content := range contents {
			items[content.ID] = ContentItem{
				ID:           content.ID,
				SiteID:       content.SiteID,
				Value:        content.Value,
				Type:         content.Type,
				LastEditedBy: content.LastEditedBy,
			}
		}
		return items, nil

	default:
		return nil, fmt.Errorf("unsupported database type: %s", c.database.GetDBType())
	}
}
