// src/routes/recipe.routes.ts
import { Router } from 'express';
import { z } from 'zod';
import * as db from '../services/db/index.db';
import { validateRequest } from '../middleware/validation.middleware';

const router = Router();

// Helper for consistent required string validation (handles missing/null/empty)
const requiredString = (message: string) => z.preprocess((val) => val ?? '', z.string().min(1, message));

// --- Zod Schemas for Recipe Routes (as per ADR-003) ---

const bySalePercentageSchema = z.object({
  query: z.object({
    minPercentage: z.coerce.number().min(0).max(100).optional().default(50),
  }),
});

const bySaleIngredientsSchema = z.object({
  query: z.object({
    minIngredients: z.coerce.number().int().positive().optional().default(3),
  }),
});

const byIngredientAndTagSchema = z.object({
  query: z.object({
    ingredient: requiredString('Query parameter "ingredient" is required.'),
    tag: requiredString('Query parameter "tag" is required.'),
  }),
});

const recipeIdParamsSchema = z.object({
  params: z.object({
    recipeId: z.coerce.number().int().positive(),
  }),
});

/**
 * GET /api/recipes/by-sale-percentage - Get recipes based on the percentage of their ingredients on sale.
 */
type BySalePercentageRequest = z.infer<typeof bySalePercentageSchema>;
router.get('/by-sale-percentage', validateRequest(bySalePercentageSchema), async (req, res, next) => {
    try {
        const { query } = req as unknown as BySalePercentageRequest;
        const minPercentage = query.minPercentage !== undefined ? Number(query.minPercentage) : 50;
        const recipes = await db.recipeRepo.getRecipesBySalePercentage(minPercentage, req.log);
        res.json(recipes);
    } catch (error) {
        req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-sale-percentage:');
        next(error);
    }
});

/**
 * GET /api/recipes/by-sale-ingredients - Get recipes by the minimum number of sale ingredients.
 */
type BySaleIngredientsRequest = z.infer<typeof bySaleIngredientsSchema>;
router.get('/by-sale-ingredients', validateRequest(bySaleIngredientsSchema), async (req, res, next) => {
    try {
        const { query } = req as unknown as BySaleIngredientsRequest;
        const minIngredients = query.minIngredients !== undefined ? Number(query.minIngredients) : 3;
        const recipes = await db.recipeRepo.getRecipesByMinSaleIngredients(minIngredients, req.log);
        res.json(recipes);
    } catch (error) {
        req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-sale-ingredients:');
        next(error);
    }
});

/**
 * GET /api/recipes/by-ingredient-and-tag - Find recipes by a specific ingredient and tag.
 */
type ByIngredientAndTagRequest = z.infer<typeof byIngredientAndTagSchema>;
router.get('/by-ingredient-and-tag', validateRequest(byIngredientAndTagSchema), async (req, res, next) => {
    try {
        const { query } = req as unknown as ByIngredientAndTagRequest;
        const recipes = await db.recipeRepo.findRecipesByIngredientAndTag(query.ingredient, query.tag, req.log);
        res.json(recipes);
    } catch (error) {
        req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-ingredient-and-tag:');
        next(error);
    }
});

/**
 * GET /api/recipes/:recipeId/comments - Get all comments for a specific recipe.
 */
type RecipeIdRequest = z.infer<typeof recipeIdParamsSchema>;
router.get('/:recipeId/comments', validateRequest(recipeIdParamsSchema), async (req, res, next) => {
    try {
        const { params } = req as unknown as RecipeIdRequest;
        const recipeId = Number(params.recipeId);
        const comments = await db.recipeRepo.getRecipeComments(recipeId, req.log);
        res.json(comments);
    } catch (error) {
        req.log.error({ error }, `Error fetching comments for recipe ID ${req.params.recipeId}:`);
        next(error);
    }
});

/**
 * GET /api/recipes/:recipeId - Get a single recipe by its ID, including ingredients and tags.
 */
router.get('/:recipeId', validateRequest(recipeIdParamsSchema), async (req, res, next) => {
    try {
        const { params } = req as unknown as RecipeIdRequest;
        const recipeId = Number(params.recipeId);
        const recipe = await db.recipeRepo.getRecipeById(recipeId, req.log);
        res.json(recipe);
    } catch (error) {
        req.log.error({ error }, `Error fetching recipe ID ${req.params.recipeId}:`);
        next(error);
    }
});

export default router;