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"
)

// BlueprintStore handles database operations for deployment blueprints
type BlueprintStore struct {
	db *gorm.DB
}

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

// Create creates a new blueprint
func (bs *BlueprintStore) Create(blueprint *models.Blueprint) error {
	// Generate ID if not provided
	if blueprint.ID == "" {
		blueprint.ID = uuid.New().String()
	}

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

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

// Update updates an existing blueprint
func (bs *BlueprintStore) Update(blueprint *models.Blueprint) error {
	return bs.db.Save(blueprint).Error
}

// Delete deletes a blueprint by ID
func (bs *BlueprintStore) Delete(id string) error {
	return bs.db.Delete(&models.Blueprint{}, "id = ?", id).Error
}

// List retrieves all blueprints with optional filtering
func (bs *BlueprintStore) List(filter map[string]interface{}) ([]*models.Blueprint, error) {
	var blueprints []*models.Blueprint

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

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

	return blueprints, nil
}

// GetBlueprintWithDeployments retrieves a blueprint by ID with associated deployments
func (bs *BlueprintStore) GetBlueprintWithDeployments(id string) (*models.Blueprint, error) {
	var blueprint models.Blueprint
	result := bs.db.Preload("Deployments").First(&blueprint, "id = ?", id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, nil // No blueprint found
		}
		return nil, fmt.Errorf("failed to get blueprint: %w", result.Error)
	}
	return &blueprint, nil
}

// GetByVersion retrieves a template by name and version
func (ts *BlueprintStore) GetByVersion(name string, version string) (*models.Blueprint, error) {
	var template models.Blueprint
	result := ts.db.Where("name = ? AND version = ?", name, version).First(&template)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, nil // No template found
		}
		return nil, fmt.Errorf("failed to get template: %w", result.Error)
	}
	return &template, nil
}
