package dbstore

import (
	"fmt"

	"git.linuxforward.com/byop/byop-engine/dbmanager"
	"git.linuxforward.com/byop/byop-engine/models"
	"github.com/google/uuid"
	"gorm.io/gorm"
)

// AppStore handles database operations for apps
type AppStore struct {
	db *gorm.DB
}

// NewAppStore creates a new AppStore
func NewAppStore(dbManager dbmanager.DbManager) *AppStore {
	return &AppStore{
		db: dbManager.GetDB(),
	}
}

// Create creates a new app
func (as *AppStore) Create(app *models.App) error {
	// Generate ID if not provided
	if app.ID == "" {
		app.ID = uuid.New().String()
	}

	// GORM will handle created_at and updated_at automatically
	return as.db.Create(app).Error
}

// GetByID retrieves an app by ID
func (as *AppStore) GetByID(id string) (*models.App, error) {
	var app models.App
	result := as.db.First(&app, "id = ?", id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, nil // No app found
		}
		return nil, fmt.Errorf("failed to get app: %w", result.Error)
	}
	return &app, nil
}

// Update updates an existing app
func (as *AppStore) Update(app *models.App) error {
	return as.db.Save(app).Error
}

// Delete deletes an app by ID
func (as *AppStore) Delete(id string) error {
	return as.db.Delete(&models.App{}, "id = ?", id).Error
}

// List retrieves all apps with optional filtering
func (as *AppStore) List(filter map[string]interface{}) ([]*models.App, error) {
	var apps []*models.App

	// Build query from filters
	query := as.db
	if filter != nil {
		for key, value := range filter {
			query = query.Where(key+" = ?", value)
		}
	}

	// Execute query
	if err := query.Find(&apps).Error; err != nil {
		return nil, fmt.Errorf("failed to list apps: %w", err)
	}

	return apps, nil
}

// GetAppWithDeployments retrieves an app by ID with associated deployments
func (as *AppStore) GetAppWithDeployments(id string) (*models.App, error) {
	var app models.App
	result := as.db.Preload("Deployments").First(&app, "id = ?", id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, nil // No app found
		}
		return nil, fmt.Errorf("failed to get app: %w", result.Error)
	}
	return &app, nil
}
