package dbstore

import (
	"context"
	"fmt"

	"git.linuxforward.com/byop/byop-engine/models"
	"gorm.io/gorm"
)

// CreateApp creates a new app using GORM
func (s *SQLiteStore) CreateApp(ctx context.Context, app *models.App) error {
	result := s.db.WithContext(ctx).Create(app)
	if result.Error != nil {
		return fmt.Errorf("failed to create app: %w", result.Error)
	}
	return nil
}

// GetAllApps retrieves all apps using GORM
func (s *SQLiteStore) GetAllApps(ctx context.Context) ([]*models.App, error) {
	var apps []*models.App
	result := s.db.WithContext(ctx).Find(&apps)
	if result.Error != nil {
		return nil, fmt.Errorf("failed to get all apps: %w", result.Error)
	}
	return apps, nil
}

// GetAppByID retrieves an app by ID using GORM
func (s *SQLiteStore) GetAppByID(ctx context.Context, id uint) (*models.App, error) {
	var app models.App
	result := s.db.WithContext(ctx).First(&app, id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, models.NewErrNotFound(fmt.Sprintf("app with ID %d not found", id), result.Error)
		}
		return nil, fmt.Errorf("failed to get app by ID: %w", result.Error)
	}
	return &app, nil
}

// GetAppsByUserID retrieves all apps for a specific user using GORM
func (s *SQLiteStore) GetAppsByUserID(ctx context.Context, userID uint) ([]*models.App, error) {
	var apps []*models.App
	result := s.db.WithContext(ctx).Where("user_id = ?", userID).Find(&apps)
	if result.Error != nil {
		return nil, fmt.Errorf("failed to get apps by user ID: %w", result.Error)
	}
	return apps, nil
}

// UpdateApp updates an existing app using GORM
func (s *SQLiteStore) UpdateApp(ctx context.Context, app *models.App) error {
	result := s.db.WithContext(ctx).Save(app)
	if result.Error != nil {
		return fmt.Errorf("failed to update app: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for update", app.ID), nil)
	}
	return nil
}

// DeleteApp deletes an app by ID using GORM
func (s *SQLiteStore) DeleteApp(ctx context.Context, id uint) error {
	result := s.db.WithContext(ctx).Delete(&models.App{}, id)
	if result.Error != nil {
		return fmt.Errorf("failed to delete app: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for deletion", id), nil)
	}
	return nil
}

// UpdateAppStatus updates the status and error message of an app using GORM
func (s *SQLiteStore) UpdateAppStatus(ctx context.Context, appID uint, status string, message string) error {
	result := s.db.WithContext(ctx).Model(&models.App{}).Where("id = ?", appID).Updates(map[string]interface{}{
		"status":    status,
		"error_msg": message,
	})
	if result.Error != nil {
		return fmt.Errorf("failed to update app status: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for status update", appID), nil)
	}
	return nil
}

// UpdateAppPreview updates the preview information of an app using GORM
func (s *SQLiteStore) UpdateAppPreview(ctx context.Context, appID uint, previewID uint, previewURL string) error {
	result := s.db.WithContext(ctx).Model(&models.App{}).Where("id = ?", appID).Updates(map[string]interface{}{
		"preview_id":  previewID,
		"preview_url": previewURL,
	})
	if result.Error != nil {
		return fmt.Errorf("failed to update app preview: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for preview update", appID), nil)
	}
	return nil
}

// UpdateAppCurrentImage updates the current image information of an app using GORM
func (s *SQLiteStore) UpdateAppCurrentImage(ctx context.Context, appID uint, imageTag string, imageURI string) error {
	result := s.db.WithContext(ctx).Model(&models.App{}).Where("id = ?", appID).Updates(map[string]interface{}{
		"current_image_tag": imageTag,
		"current_image_uri": imageURI,
	})
	if result.Error != nil {
		return fmt.Errorf("failed to update app current image: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("app with ID %d not found for image update", appID), nil)
	}
	return nil
}
