package repository

import (
	"apskel-pos-be/internal/entities"
	"context"

	"gorm.io/gorm"

	"github.com/google/uuid"
)

type ProductRecipeRepository struct {
	db *gorm.DB
}

func NewProductRecipeRepository(db *gorm.DB) *ProductRecipeRepository {
	return &ProductRecipeRepository{db: db}
}

func (r *ProductRecipeRepository) Create(ctx context.Context, productRecipe *entities.ProductRecipe) error {
	return r.db.WithContext(ctx).Create(productRecipe).Error
}

func (r *ProductRecipeRepository) GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.ProductRecipe, error) {
	var productRecipe entities.ProductRecipe
	err := r.db.WithContext(ctx).
		Preload("Product").
		Preload("ProductVariant").
		Preload("Ingredient").
		Where("id = ? AND organization_id = ?", id, organizationID).
		First(&productRecipe).Error
	if err != nil {
		return nil, err
	}
	return &productRecipe, nil
}

func (r *ProductRecipeRepository) GetByProductID(ctx context.Context, productID, organizationID uuid.UUID) ([]*entities.ProductRecipe, error) {
	var productRecipes []*entities.ProductRecipe
	err := r.db.WithContext(ctx).
		Preload("Product").
		Preload("ProductVariant").
		Preload("Ingredient").
		Where("product_id = ? AND organization_id = ?", productID, organizationID).
		Order("created_at DESC").
		Find(&productRecipes).Error
	if err != nil {
		return nil, err
	}
	return productRecipes, nil
}

func (r *ProductRecipeRepository) GetByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) ([]*entities.ProductRecipe, error) {
	var productRecipes []*entities.ProductRecipe
	query := r.db.WithContext(ctx).
		Preload("Product").
		Preload("ProductVariant").
		Preload("Ingredient").
		Where("product_id = ? AND organization_id = ?", productID, organizationID)

	if variantID != nil {
		query = query.Where("variant_id = ?", *variantID)
	} else {
		query = query.Where("variant_id IS NULL")
	}

	err := query.Order("created_at DESC").Find(&productRecipes).Error
	if err != nil {
		return nil, err
	}
	return productRecipes, nil
}

func (r *ProductRecipeRepository) GetByIngredientID(ctx context.Context, ingredientID, organizationID uuid.UUID) ([]*entities.ProductRecipe, error) {
	var productRecipes []*entities.ProductRecipe
	err := r.db.WithContext(ctx).
		Preload("Product").
		Preload("ProductVariant").
		Preload("Ingredient").
		Where("ingredient_id = ? AND organization_id = ?", ingredientID, organizationID).
		Order("created_at DESC").
		Find(&productRecipes).Error
	if err != nil {
		return nil, err
	}
	return productRecipes, nil
}

func (r *ProductRecipeRepository) Update(ctx context.Context, productRecipe *entities.ProductRecipe) error {
	return r.db.WithContext(ctx).
		Where("id = ? AND organization_id = ?", productRecipe.ID, productRecipe.OrganizationID).
		Updates(productRecipe).Error
}

func (r *ProductRecipeRepository) Delete(ctx context.Context, id, organizationID uuid.UUID) error {
	result := r.db.WithContext(ctx).
		Where("id = ? AND organization_id = ?", id, organizationID).
		Delete(&entities.ProductRecipe{})
	
	if result.Error != nil {
		return result.Error
	}
	
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	
	return nil
}

func (r *ProductRecipeRepository) DeleteByProductID(ctx context.Context, productID, organizationID uuid.UUID) error {
	return r.db.WithContext(ctx).
		Where("product_id = ? AND organization_id = ?", productID, organizationID).
		Delete(&entities.ProductRecipe{}).Error
}

func (r *ProductRecipeRepository) DeleteByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) error {
	query := r.db.WithContext(ctx).Where("product_id = ? AND organization_id = ?", productID, organizationID)
	
	if variantID != nil {
		query = query.Where("variant_id = ?", *variantID)
	} else {
		query = query.Where("variant_id IS NULL")
	}
	
	return query.Delete(&entities.ProductRecipe{}).Error
}