import type { Endpoint } from 'payload'
import { isSuperAdmin } from '@/access/isSuperAdmin'
import { canAccessKitchen } from '@/access/roles'

/**
 * Field mappings for aggregation
 * Maps meal type to their respective boolean fields that should be counted
 */
const breakfastFields = {
  'breakfast.accordingToPlan': 'According to Plan',
  'breakfast.bread.breadRoll': 'Bread Roll (Brötchen)',
  'breakfast.bread.wholeGrainRoll': 'Whole Grain Roll (Vollkornbrötchen)',
  'breakfast.bread.greyBread': 'Grey Bread (Graubrot)',
  'breakfast.bread.wholeGrainBread': 'Whole Grain Bread (Vollkornbrot)',
  'breakfast.bread.whiteBread': 'White Bread (Weißbrot)',
  'breakfast.bread.crispbread': 'Crispbread (Knäckebrot)',
  'breakfast.porridge': 'Porridge (Brei)',
  'breakfast.preparation.sliced': 'Sliced (geschnitten)',
  'breakfast.preparation.spread': 'Spread (geschmiert)',
  'breakfast.spreads.butter': 'Butter',
  'breakfast.spreads.margarine': 'Margarine',
  'breakfast.spreads.jam': 'Jam (Konfitüre)',
  'breakfast.spreads.diabeticJam': 'Diabetic Jam (Diab. Konfitüre)',
  'breakfast.spreads.honey': 'Honey (Honig)',
  'breakfast.spreads.cheese': 'Cheese (Käse)',
  'breakfast.spreads.quark': 'Quark',
  'breakfast.spreads.sausage': 'Sausage (Wurst)',
  'breakfast.beverages.coffee': 'Coffee (Kaffee)',
  'breakfast.beverages.tea': 'Tea (Tee)',
  'breakfast.beverages.hotMilk': 'Hot Milk (Milch heiß)',
  'breakfast.beverages.coldMilk': 'Cold Milk (Milch kalt)',
  'breakfast.additions.sugar': 'Sugar (Zucker)',
  'breakfast.additions.sweetener': 'Sweetener (Süßstoff)',
  'breakfast.additions.coffeeCreamer': 'Coffee Creamer (Kaffeesahne)',
}

const lunchFields = {
  'lunch.soup': 'Soup (Suppe)',
  'lunch.dessert': 'Dessert',
  'lunch.specialPreparations.pureedFood': 'Pureed Food (passierte Kost)',
  'lunch.specialPreparations.pureedMeat': 'Pureed Meat (passiertes Fleisch)',
  'lunch.specialPreparations.slicedMeat': 'Sliced Meat (geschnittenes Fleisch)',
  'lunch.specialPreparations.mashedPotatoes': 'Mashed Potatoes (Kartoffelbrei)',
  'lunch.restrictions.noFish': 'No Fish (ohne Fisch)',
  'lunch.restrictions.fingerFood': 'Finger Food',
  'lunch.restrictions.onlySweet': 'Only Sweet (nur süß)',
}

const dinnerFields = {
  'dinner.accordingToPlan': 'According to Plan',
  'dinner.bread.greyBread': 'Grey Bread (Graubrot)',
  'dinner.bread.wholeGrainBread': 'Whole Grain Bread (Vollkornbrot)',
  'dinner.bread.whiteBread': 'White Bread (Weißbrot)',
  'dinner.bread.crispbread': 'Crispbread (Knäckebrot)',
  'dinner.preparation.spread': 'Spread (geschmiert)',
  'dinner.preparation.sliced': 'Sliced (geschnitten)',
  'dinner.spreads.butter': 'Butter',
  'dinner.spreads.margarine': 'Margarine',
  'dinner.soup': 'Soup (Suppe)',
  'dinner.porridge': 'Porridge (Brei)',
  'dinner.noFish': 'No Fish (ohne Fisch)',
  'dinner.beverages.tea': 'Tea (Tee)',
  'dinner.beverages.cocoa': 'Cocoa (Kakao)',
  'dinner.beverages.hotMilk': 'Hot Milk (Milch heiß)',
  'dinner.beverages.coldMilk': 'Cold Milk (Milch kalt)',
  'dinner.additions.sugar': 'Sugar (Zucker)',
  'dinner.additions.sweetener': 'Sweetener (Süßstoff)',
}

/**
 * Get nested value from object using dot notation path
 */
function getNestedValue(obj: Record<string, unknown>, path: string): unknown {
  return path.split('.').reduce((current: unknown, key) => {
    if (current && typeof current === 'object' && key in (current as Record<string, unknown>)) {
      return (current as Record<string, unknown>)[key]
    }
    return undefined
  }, obj)
}

/**
 * Kitchen Report API Endpoint
 *
 * GET /api/meals/kitchen-report
 *
 * Query Parameters:
 * - date (required): YYYY-MM-DD format
 * - mealType (required): breakfast | lunch | dinner
 * - order (optional): filter by meal order ID
 *
 * Returns aggregated ingredient counts for the specified date and meal type.
 * Only accessible by users with admin or kitchen role.
 */
export const kitchenReportEndpoint: Endpoint = {
  path: '/kitchen-report',
  method: 'get',
  handler: async (req) => {
    const { payload, user } = req

    // Check authentication
    if (!user) {
      return Response.json({ error: 'Unauthorized' }, { status: 401 })
    }

    // Check authorization - must be super admin, tenant admin, or kitchen staff
    if (!isSuperAdmin(user) && !canAccessKitchen(user)) {
      return Response.json(
        { error: 'Forbidden - Kitchen or Admin role required' },
        { status: 403 },
      )
    }

    // Parse query parameters
    const url = new URL(req.url || '', 'http://localhost')
    const date = url.searchParams.get('date')
    const mealType = url.searchParams.get('mealType')
    const orderId = url.searchParams.get('order')

    // Validate parameters
    if (!date) {
      return Response.json({ error: 'Missing required parameter: date' }, { status: 400 })
    }

    if (!mealType || !['breakfast', 'lunch', 'dinner'].includes(mealType)) {
      return Response.json(
        { error: 'Invalid or missing mealType. Must be: breakfast, lunch, or dinner' },
        { status: 400 },
      )
    }

    // Validate date format
    const dateRegex = /^\d{4}-\d{2}-\d{2}$/
    if (!dateRegex.test(date)) {
      return Response.json({ error: 'Invalid date format. Use YYYY-MM-DD' }, { status: 400 })
    }

    try {
      // Build the where clause
      const whereClause: {
        and: Array<{ date?: { equals: string }; mealType?: { equals: string }; order?: { equals: number } }>
      } = {
        and: [
          { date: { equals: date } },
          { mealType: { equals: mealType } },
        ],
      }

      // Optionally filter by meal order
      if (orderId) {
        whereClause.and.push({ order: { equals: Number(orderId) } })
      }

      // Query meals for the specified date and meal type
      const meals = await payload.find({
        collection: 'meals',
        where: whereClause,
        limit: 1000, // Get all meals for the day
        depth: 2, // Include resident and formImage details
      })

      // Select the appropriate field mapping
      const fieldMapping =
        mealType === 'breakfast'
          ? breakfastFields
          : mealType === 'lunch'
            ? lunchFields
            : dinnerFields

      // Aggregate counts
      const ingredients: Record<string, { count: number; label: string }> = {}

      // Initialize all fields with 0
      for (const [fieldPath, label] of Object.entries(fieldMapping)) {
        ingredients[fieldPath] = { count: 0, label }
      }

      // Count lunch portion sizes separately
      const portionSizes: Record<string, number> = {
        small: 0,
        large: 0,
        vegetarian: 0,
      }

      // Count occurrences
      for (const meal of meals.docs) {
        // Count boolean fields
        for (const fieldPath of Object.keys(fieldMapping)) {
          const value = getNestedValue(meal as unknown as Record<string, unknown>, fieldPath)
          if (value === true) {
            ingredients[fieldPath].count++
          }
        }

        // Count lunch portion sizes
        if (mealType === 'lunch' && meal.lunch?.portionSize) {
          const size = meal.lunch.portionSize as string
          if (size in portionSizes) {
            portionSizes[size]++
          }
        }
      }

      // Build response with non-zero items
      const ingredientCounts: Record<string, number> = {}
      const ingredientLabels: Record<string, string> = {}

      for (const [fieldPath, { count, label }] of Object.entries(ingredients)) {
        if (count > 0) {
          // Use a cleaner key name (last part of the path)
          const key = fieldPath.split('.').pop() || fieldPath
          ingredientCounts[key] = count
          ingredientLabels[key] = label
        }
      }

      // Extract meals with form images for kitchen reference
      interface MealWithImage {
        id: number
        residentName: string
        residentRoom: string
        status: string
        formImageUrl?: string
        formImageThumbnail?: string
      }

      const mealsWithImages: MealWithImage[] = meals.docs
        .filter((meal) => meal.formImage && typeof meal.formImage === 'object')
        .map((meal) => {
          const resident = typeof meal.resident === 'object' ? meal.resident : null
          const formImage = meal.formImage as { url?: string; sizes?: { thumbnail?: { url?: string } } }
          return {
            id: meal.id,
            residentName: resident?.name || 'Unknown',
            residentRoom: resident?.room || '-',
            status: meal.status,
            formImageUrl: formImage?.url,
            formImageThumbnail: formImage?.sizes?.thumbnail?.url || formImage?.url,
          }
        })

      // Build the response
      const response: Record<string, unknown> = {
        date,
        mealType,
        totalMeals: meals.totalDocs,
        ingredients: ingredientCounts,
        labels: ingredientLabels,
        mealsWithImages,
      }

      // Add portion sizes for lunch
      if (mealType === 'lunch') {
        const nonZeroPortions: Record<string, number> = {}
        for (const [size, count] of Object.entries(portionSizes)) {
          if (count > 0) {
            nonZeroPortions[size] = count
          }
        }
        if (Object.keys(nonZeroPortions).length > 0) {
          response.portionSizes = nonZeroPortions
        }
      }

      return Response.json(response, { status: 200 })
    } catch (error) {
      console.error('Kitchen report error:', error)
      return Response.json({ error: 'Failed to generate report' }, { status: 500 })
    }
  },
}
