<?php

require_once __DIR__ . '/chore_helpers.php';
require_once __DIR__ . '/grocery_helpers.php';

const MEAL_SLOT_BREAKFAST = 'breakfast';
const MEAL_SLOT_LUNCH = 'lunch';
const MEAL_SLOT_DINNER = 'dinner';

/** @return array<int, string> */
function mealSlotTypes(): array {
    return [MEAL_SLOT_BREAKFAST, MEAL_SLOT_LUNCH, MEAL_SLOT_DINNER];
}

function mealCurrentWeekStart(): string {
    try {
        $d = new DateTimeImmutable('monday this week');
        return $d->format('Y-m-d');
    } catch (Exception $e) {
        return gmdate('Y-m-d');
    }
}

/**
 * @return array<string, array<string, string|null>>
 */
function mealDefaultEmptySlots(): array {
    $slots = [];
    for ($i = 0; $i < 7; $i++) {
        $key = (string) $i;
        $slots[$key] = [
            MEAL_SLOT_BREAKFAST => null,
            MEAL_SLOT_LUNCH => null,
            MEAL_SLOT_DINNER => null,
        ];
    }
    return $slots;
}

/**
 * @param mixed $raw
 * @return array{weekStart: string, slots: array<string, array<string, string|null>>}
 */
function normalizeMealPlan($raw): array {
    $base = [
        'weekStart' => mealCurrentWeekStart(),
        'slots' => mealDefaultEmptySlots(),
    ];
    if (!is_array($raw)) {
        return $base;
    }
    $ws = isset($raw['weekStart']) ? trim((string) $raw['weekStart']) : '';
    if ($ws !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $ws)) {
        $base['weekStart'] = $ws;
    }
    $slotsIn = $raw['slots'] ?? [];
    if (is_array($slotsIn)) {
        for ($i = 0; $i < 7; $i++) {
            $key = (string) $i;
            $day = $slotsIn[$key] ?? $slotsIn[$i] ?? [];
            if (!is_array($day)) {
                continue;
            }
            foreach (mealSlotTypes() as $mt) {
                $mid = $day[$mt] ?? null;
                if ($mid === null || $mid === '') {
                    $base['slots'][$key][$mt] = null;
                } else {
                    $base['slots'][$key][$mt] = is_string($mid) ? $mid : null;
                }
            }
        }
    }
    return $base;
}

function loadMealPlan(): array {
    return normalizeMealPlan(readJsonFile('meal_plans.json'));
}

/**
 * @param mixed $raw
 * @return array<int, array<string, mixed>>
 */
function normalizeMealsList($raw): array {
    if (!is_array($raw) || !array_is_list($raw)) {
        return [];
    }
    $out = [];
    foreach ($raw as $row) {
        if (is_array($row) && !empty($row['id']) && is_string($row['id'])) {
            $out[] = $row;
        }
    }
    return $out;
}

/**
 * @param array<string, mixed> $m
 * @return array<string, mixed>
 */
function normalizeMealRow(array $m): array {
    if (isset($m['name']) && !isset($m['title'])) {
        $m['title'] = trim((string) $m['name']);
    }
    $m['title'] = trim((string) ($m['title'] ?? ''));
    $m['image'] = trim((string) ($m['image'] ?? ''));
    $m['description'] = trim((string) ($m['description'] ?? ''));
    $m['directions'] = trim((string) ($m['directions'] ?? ''));
    if (!isset($m['lists']) || !is_array($m['lists'])) {
        $m['lists'] = [];
    }
    $m['lists'] = normalizeChoreLists($m['lists']);
    $tags = $m['tags'] ?? [];
    if (!is_array($tags)) {
        $tags = [];
    }
    $cleanTags = [];
    foreach ($tags as $t) {
        $t = strtolower(trim((string) $t));
        if (in_array($t, ['breakfast', 'lunch', 'dinner'], true)) {
            $cleanTags[] = $t;
        }
    }
    if (isset($m['type']) && is_string($m['type']) && count($cleanTags) === 0) {
        $tt = strtolower(trim($m['type']));
        if (in_array($tt, ['breakfast', 'lunch', 'dinner'], true)) {
            $cleanTags[] = $tt;
        }
    }
    $m['tags'] = array_values(array_unique($cleanTags));
    $ing = $m['ingredients'] ?? [];
    if (!is_array($ing)) {
        $ing = [];
    }
    $ingOut = [];
    foreach ($ing as $line) {
        $s = trim((string) $line);
        if ($s !== '') {
            $ingOut[] = $s;
        }
    }
    $m['ingredients'] = $ingOut;
    $items = $m['items'] ?? [];
    if (!is_array($items)) {
        $items = [];
    }
    $itemOut = [];
    foreach ($items as $it) {
        if (!is_array($it)) {
            continue;
        }
        $nm = trim((string) ($it['name'] ?? ''));
        if ($nm === '') {
            continue;
        }
        $itemOut[] = [
            'name' => $nm,
            'storeId' => trim((string) ($it['storeId'] ?? '')),
            'description' => trim((string) ($it['description'] ?? '')),
            'size' => trim((string) ($it['size'] ?? '')),
            'quantity' => trim((string) ($it['quantity'] ?? '1')) ?: '1',
            'price' => trim((string) ($it['price'] ?? '')),
            'image' => trim((string) ($it['image'] ?? '')),
        ];
    }
    $m['items'] = $itemOut;
    if (!isset($m['author_id'])) {
        $m['author_id'] = '';
    }
    return $m;
}

/**
 * @param array<int, array<string, mixed>> $meals
 */
function findMealById(array $meals, string $id): ?array {
    foreach ($meals as $m) {
        if (($m['id'] ?? '') === $id) {
            return $m;
        }
    }
    return null;
}

/**
 * @param array<int, array<string, mixed>> $meals
 */
function findMealIndexById(array $meals, string $id): ?int {
    foreach ($meals as $i => $m) {
        if (($m['id'] ?? '') === $id) {
            return $i;
        }
    }
    return null;
}

/**
 * Migrate legacy meals (name, date, type) into library format.
 *
 * @param array<int, array<string, mixed>> $meals
 * @return array<int, array<string, mixed>>
 */
function migrateLegacyMealsList(array $meals): array {
    $out = [];
    foreach ($meals as $m) {
        if (!is_array($m)) {
            continue;
        }
        if (isset($m['title']) && isset($m['tags'])) {
            $out[] = normalizeMealRow($m);
            continue;
        }
        $title = trim((string) ($m['title'] ?? $m['name'] ?? ''));
        if ($title === '') {
            continue;
        }
        $tags = [];
        if (!empty($m['type'])) {
            $tt = strtolower(trim((string) $m['type']));
            if (in_array($tt, ['breakfast', 'lunch', 'dinner'], true)) {
                $tags[] = $tt;
            }
        }
        $out[] = normalizeMealRow([
            'id' => !empty($m['id']) && is_string($m['id']) ? $m['id'] : bin2hex(random_bytes(8)),
            'title' => $title,
            'tags' => $tags,
            'description' => isset($m['date']) ? 'Legacy date: ' . (string) $m['date'] : '',
            'image' => '',
            'directions' => '',
            'lists' => [],
            'ingredients' => [],
            'items' => [],
            'author_id' => '',
        ]);
    }
    return $out;
}

/**
 * Push meal shopping items to grocery lists as pending_review.
 *
 * @param array<int, array<string, mixed>> $stores
 * @return int number of lines added
 */
function pushMealItemsToGrocery(array $meal, array $stores): int {
    $items = $meal['items'] ?? [];
    if (!is_array($items) || count($items) === 0) {
        return 0;
    }
    $mealId = (string) ($meal['id'] ?? '');
    $mealTitle = (string) ($meal['title'] ?? '');
    return groceryAppendMealItemRowsBatch($stores, $items, $mealId, $mealTitle);
}

function mealDayShortLabel(string $weekStart, int $offset): string {
    $ts = strtotime($weekStart . ' UTC +' . $offset . ' days');
    if ($ts === false) {
        return (string) $offset;
    }
    return gmdate('D n/j', $ts);
}
