package store

// import (
// 	"context"
// 	"encoding/json"
// 	"fmt"
// 	"strings"
// 	"time"

// 	"github.com/google/uuid"

// 	"git.warky.dev/wdevs/amcs/internal/generatedmodels"
// 	ext "git.warky.dev/wdevs/amcs/internal/types"
// )

// func (db *DB) AddRecipe(ctx context.Context, r ext.Recipe) (ext.Recipe, error) {
// 	ingredients, err := json.Marshal(r.Ingredients)
// 	if err != nil {
// 		return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
// 	}
// 	instructions, err := json.Marshal(r.Instructions)
// 	if err != nil {
// 		return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
// 	}
// 	if r.Tags == nil {
// 		r.Tags = []string{}
// 	}

// 	row := db.pool.QueryRow(ctx, `
// 		insert into recipes (name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags, rating, notes)
// 		values ($1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, $8, $9, $10)
// 		returning id, created_at, updated_at
// 	`, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
// 		ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))

// 	created := r
// 	var model generatedmodels.ModelPublicRecipes
// 	if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
// 		return ext.Recipe{}, fmt.Errorf("insert recipe: %w", err)
// 	}
// 	created.ID = model.ID.UUID()
// 	created.CreatedAt = model.CreatedAt.Time()
// 	created.UpdatedAt = model.UpdatedAt.Time()
// 	return created, nil
// }

// func (db *DB) SearchRecipes(ctx context.Context, query, cuisine string, tags []string, ingredient string) ([]ext.Recipe, error) {
// 	args := []any{}
// 	conditions := []string{}

// 	if q := strings.TrimSpace(query); q != "" {
// 		args = append(args, "%"+q+"%")
// 		conditions = append(conditions, fmt.Sprintf("name ILIKE $%d", len(args)))
// 	}
// 	if c := strings.TrimSpace(cuisine); c != "" {
// 		args = append(args, c)
// 		conditions = append(conditions, fmt.Sprintf("cuisine = $%d", len(args)))
// 	}
// 	if len(tags) > 0 {
// 		args = append(args, tags)
// 		conditions = append(conditions, fmt.Sprintf("tags @> $%d", len(args)))
// 	}
// 	if ing := strings.TrimSpace(ingredient); ing != "" {
// 		args = append(args, "%"+ing+"%")
// 		conditions = append(conditions, fmt.Sprintf("ingredients::text ILIKE $%d", len(args)))
// 	}

// 	q := `select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at from recipes`
// 	if len(conditions) > 0 {
// 		q += " where " + strings.Join(conditions, " and ")
// 	}
// 	q += " order by name"

// 	rows, err := db.pool.Query(ctx, q, args...)
// 	if err != nil {
// 		return nil, fmt.Errorf("search recipes: %w", err)
// 	}
// 	defer rows.Close()

// 	var recipes []ext.Recipe
// 	for rows.Next() {
// 		r, err := scanRecipeRow(rows)
// 		if err != nil {
// 			return nil, err
// 		}
// 		recipes = append(recipes, r)
// 	}
// 	return recipes, rows.Err()
// }

// func (db *DB) GetRecipe(ctx context.Context, id uuid.UUID) (ext.Recipe, error) {
// 	row := db.pool.QueryRow(ctx, `
// 		select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at
// 		from recipes where id = $1
// 	`, id)

// 	var model generatedmodels.ModelPublicRecipes
// 	var tags []string
// 	if err := row.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
// 		&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
// 		return ext.Recipe{}, fmt.Errorf("get recipe: %w", err)
// 	}
// 	if tags == nil {
// 		tags = []string{}
// 	}
// 	return recipeFromModel(model, tags), nil
// }

// func (db *DB) UpdateRecipe(ctx context.Context, id uuid.UUID, r ext.Recipe) (ext.Recipe, error) {
// 	ingredients, err := json.Marshal(r.Ingredients)
// 	if err != nil {
// 		return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
// 	}
// 	instructions, err := json.Marshal(r.Instructions)
// 	if err != nil {
// 		return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
// 	}
// 	if r.Tags == nil {
// 		r.Tags = []string{}
// 	}

// 	_, err = db.pool.Exec(ctx, `
// 		update recipes set
// 			name = $2, cuisine = $3, prep_time_minutes = $4, cook_time_minutes = $5,
// 			servings = $6, ingredients = $7::jsonb, instructions = $8::jsonb,
// 			tags = $9, rating = $10, notes = $11
// 		where id = $1
// 	`, id, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
// 		ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
// 	if err != nil {
// 		return ext.Recipe{}, fmt.Errorf("update recipe: %w", err)
// 	}
// 	return db.GetRecipe(ctx, id)
// }

// func (db *DB) CreateMealPlan(ctx context.Context, weekStart time.Time, entries []ext.MealPlanInput) ([]ext.MealPlanEntry, error) {
// 	if _, err := db.pool.Exec(ctx, `delete from meal_plans where week_start = $1`, weekStart); err != nil {
// 		return nil, fmt.Errorf("clear meal plan: %w", err)
// 	}

// 	var results []ext.MealPlanEntry
// 	for _, e := range entries {
// 		row := db.pool.QueryRow(ctx, `
// 			insert into meal_plans (week_start, day_of_week, meal_type, recipe_id, custom_meal, servings, notes)
// 			values ($1, $2, $3, $4, $5, $6, $7)
// 			returning id, created_at
// 		`, weekStart, e.DayOfWeek, e.MealType, e.RecipeID, nullStr(e.CustomMeal), e.Servings, nullStr(e.Notes))

// 		entry := ext.MealPlanEntry{
// 			WeekStart:  weekStart,
// 			DayOfWeek:  e.DayOfWeek,
// 			MealType:   e.MealType,
// 			RecipeID:   e.RecipeID,
// 			CustomMeal: e.CustomMeal,
// 			Servings:   e.Servings,
// 			Notes:      e.Notes,
// 		}
// 		var model generatedmodels.ModelPublicMealPlans
// 		if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
// 			return nil, fmt.Errorf("insert meal plan entry: %w", err)
// 		}
// 		entry.ID = model.ID.UUID()
// 		entry.CreatedAt = model.CreatedAt.Time()
// 		results = append(results, entry)
// 	}
// 	return results, nil
// }

// func (db *DB) GetMealPlan(ctx context.Context, weekStart time.Time) ([]ext.MealPlanEntry, error) {
// 	rows, err := db.pool.Query(ctx, `
// 		select mp.id, mp.week_start, mp.day_of_week, mp.meal_type, mp.recipe_id, r.name, mp.custom_meal, mp.servings, mp.notes, mp.created_at
// 		from meal_plans mp
// 		left join recipes r on r.id = mp.recipe_id
// 		where mp.week_start = $1
// 		order by
// 			case mp.day_of_week
// 				when 'monday' then 1 when 'tuesday' then 2 when 'wednesday' then 3
// 				when 'thursday' then 4 when 'friday' then 5 when 'saturday' then 6
// 				when 'sunday' then 7 else 8
// 			end,
// 			case mp.meal_type
// 				when 'breakfast' then 1 when 'lunch' then 2 when 'dinner' then 3
// 				when 'snack' then 4 else 5
// 			end
// 	`, weekStart)
// 	if err != nil {
// 		return nil, fmt.Errorf("get meal plan: %w", err)
// 	}
// 	defer rows.Close()

// 	var entries []ext.MealPlanEntry
// 	for rows.Next() {
// 		var model generatedmodels.ModelPublicMealPlans
// 		var recipeName *string
// 		if err := rows.Scan(&model.ID, &model.WeekStart, &model.DayOfWeek, &model.MealType, &model.RecipeID, &recipeName, &model.CustomMeal, &model.Servings, &model.Notes, &model.CreatedAt); err != nil {
// 			return nil, fmt.Errorf("scan meal plan entry: %w", err)
// 		}
// 		entries = append(entries, mealPlanEntryFromModel(model, strVal(recipeName)))
// 	}
// 	return entries, rows.Err()
// }

// func (db *DB) GenerateShoppingList(ctx context.Context, weekStart time.Time) (ext.ShoppingList, error) {
// 	entries, err := db.GetMealPlan(ctx, weekStart)
// 	if err != nil {
// 		return ext.ShoppingList{}, err
// 	}

// 	recipeIDs := map[uuid.UUID]bool{}
// 	for _, e := range entries {
// 		if e.RecipeID != nil {
// 			recipeIDs[*e.RecipeID] = true
// 		}
// 	}

// 	aggregated := map[string]*ext.ShoppingItem{}
// 	for id := range recipeIDs {
// 		recipe, err := db.GetRecipe(ctx, id)
// 		if err != nil {
// 			continue
// 		}
// 		for _, ing := range recipe.Ingredients {
// 			key := strings.ToLower(ing.Name)
// 			if existing, ok := aggregated[key]; ok {
// 				if ing.Quantity != "" {
// 					existing.Quantity += "+" + ing.Quantity
// 				}
// 			} else {
// 				recipeIDCopy := id
// 				aggregated[key] = &ext.ShoppingItem{
// 					Name:      ing.Name,
// 					Quantity:  ing.Quantity,
// 					Unit:      ing.Unit,
// 					Purchased: false,
// 					RecipeID:  &recipeIDCopy,
// 				}
// 			}
// 		}
// 	}

// 	items := make([]ext.ShoppingItem, 0, len(aggregated))
// 	for _, item := range aggregated {
// 		items = append(items, *item)
// 	}

// 	itemsJSON, err := json.Marshal(items)
// 	if err != nil {
// 		return ext.ShoppingList{}, fmt.Errorf("marshal shopping items: %w", err)
// 	}

// 	row := db.pool.QueryRow(ctx, `
// 		insert into shopping_lists (week_start, items)
// 		values ($1, $2::jsonb)
// 		on conflict (week_start) do update set items = excluded.items, updated_at = now()
// 		returning id, created_at, updated_at
// 	`, weekStart, itemsJSON)

// 	var model generatedmodels.ModelPublicShoppingLists
// 	list := ext.ShoppingList{WeekStart: weekStart, Items: items}
// 	if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
// 		return ext.ShoppingList{}, fmt.Errorf("upsert shopping list: %w", err)
// 	}
// 	list.ID = model.ID.UUID()
// 	list.CreatedAt = model.CreatedAt.Time()
// 	list.UpdatedAt = model.UpdatedAt.Time()
// 	return list, nil
// }

// func scanRecipeRow(rows interface{ Scan(...any) error }) (ext.Recipe, error) {
// 	var model generatedmodels.ModelPublicRecipes
// 	var tags []string
// 	if err := rows.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
// 		&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
// 		return ext.Recipe{}, fmt.Errorf("scan recipe: %w", err)
// 	}
// 	if tags == nil {
// 		tags = []string{}
// 	}
// 	return recipeFromModel(model, tags), nil
// }
