package dbstore

import (
	"context"
	"fmt"

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

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

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

// GetPreviewByAppID retrieves a preview by app ID using GORM
func (s *SQLiteStore) GetPreviewByAppID(ctx context.Context, appID uint) (*models.Preview, error) {
	var preview models.Preview
	result := s.db.WithContext(ctx).Where("app_id = ?", appID).First(&preview)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, models.NewErrNotFound(fmt.Sprintf("preview for app ID %d not found", appID), result.Error)
		}
		return nil, fmt.Errorf("failed to get preview by app ID: %w", result.Error)
	}
	return &preview, nil
}

// GetPreviewsByAppID retrieves all previews for an app using GORM
func (s *SQLiteStore) GetPreviewsByAppID(ctx context.Context, appID uint) ([]*models.Preview, error) {
	var previews []*models.Preview
	result := s.db.WithContext(ctx).Where("app_id = ?", appID).Find(&previews)
	if result.Error != nil {
		return nil, fmt.Errorf("failed to get previews by app ID: %w", result.Error)
	}
	return previews, nil
}

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

// GetPreviewsByStatus retrieves previews by status using GORM
func (s *SQLiteStore) GetPreviewsByStatus(ctx context.Context, status string) ([]*models.Preview, error) {
	var previews []*models.Preview
	result := s.db.WithContext(ctx).Where("status = ?", status).Find(&previews)
	if result.Error != nil {
		return nil, fmt.Errorf("failed to get previews by status: %w", result.Error)
	}
	return previews, nil
}

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

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

// UpdatePreviewVPS updates VPS information for a preview using GORM
func (s *SQLiteStore) UpdatePreviewVPS(ctx context.Context, previewID uint, vpsID string, ipAddress string, previewURL string) error {
	result := s.db.WithContext(ctx).Model(&models.Preview{}).Where("id = ?", previewID).Updates(map[string]interface{}{
		"vps_id":     vpsID,
		"ip_address": ipAddress,
		"url":        previewURL,
	})
	if result.Error != nil {
		return fmt.Errorf("failed to update preview VPS: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for VPS update", previewID), nil)
	}
	return nil
}

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

// UpdatePreviewBuildLogs updates the build logs of a preview using GORM
func (s *SQLiteStore) UpdatePreviewBuildLogs(ctx context.Context, previewID uint, logs string) error {
	result := s.db.WithContext(ctx).Model(&models.Preview{}).Where("id = ?", previewID).Update("build_logs", logs)
	if result.Error != nil {
		return fmt.Errorf("failed to update preview build logs: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for build logs update", previewID), nil)
	}
	return nil
}

// UpdatePreviewDeployLogs updates the deploy logs of a preview using GORM
func (s *SQLiteStore) UpdatePreviewDeployLogs(ctx context.Context, previewID uint, logs string) error {
	result := s.db.WithContext(ctx).Model(&models.Preview{}).Where("id = ?", previewID).Update("deploy_logs", logs)
	if result.Error != nil {
		return fmt.Errorf("failed to update preview deploy logs: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("preview with ID %d not found for deploy logs update", previewID), nil)
	}
	return nil
}
