<?php

class MenuController extends Controller
{
    public function index(): void
    {
        Auth::requirePermission('menu', 'view');

        $categoryModel = new MenuCategory();
        $menuItemModel = new MenuItem();

        $this->view('menu.index', [
            'pageTitle'  => 'Menu Management',
            'categories' => $categoryModel->allOrdered(),
            'items'      => $menuItemModel->allWithCategory(),
            'csrf'       => $this->csrfField(),
        ]);
    }

    public function today(): void
    {
        Auth::requirePermission('menu', 'view');

        $menuItemModel = new MenuItem();
        $this->view('menu.today', [
            'pageTitle'      => "Today's Menu",
            'menuByCategory' => $menuItemModel->getMenuForPos(),
        ]);
    }

    // --- Categories ---

    public function storeCategory(): void
    {
        Auth::requirePermission('menu', 'add');
        $this->verifyCsrf();

        $name = trim($this->input('category_name', ''));
        if ($name === '') {
            $this->redirect('menu');
            return;
        }

        $categoryModel = new MenuCategory();
        $categoryModel->insert([
            'category_name'  => $name,
            'display_order'  => $categoryModel->nextDisplayOrder(),
            'is_active'      => 1,
        ]);

        AuditLogger::log(Auth::id(), 'MENU_CATEGORY_CREATE', 'menu', "Added category: {$name}");
        $this->redirect('menu');
    }

    public function toggleCategory(): void
    {
        Auth::requirePermission('menu', 'edit');
        $this->verifyCsrf();

        $id = (int) $this->input('id');
        $categoryModel = new MenuCategory();
        $cat = $categoryModel->find($id);
        if ($cat) {
            $categoryModel->update($id, ['is_active' => $cat['is_active'] ? 0 : 1]);
            AuditLogger::log(Auth::id(), 'MENU_CATEGORY_TOGGLE', 'menu', "Category #{$id} active -> " . ($cat['is_active'] ? '0' : '1'));
        }
        $this->redirect('menu');
    }

    public function deleteCategory(): void
    {
        Auth::requirePermission('menu', 'delete');
        $this->verifyCsrf();

        $id = (int) $this->input('id');
        $categoryModel = new MenuCategory();
        $cat = $categoryModel->find($id);
        if ($cat && (int) $cat['item_count'] === 0) {
            $categoryModel->delete($id);
            AuditLogger::log(Auth::id(), 'MENU_CATEGORY_DELETE', 'menu', "Deleted category #{$id}");
        }
        $this->redirect('menu');
    }

    // --- Items ---

    public function createItem(): void
    {
        Auth::requirePermission('menu', 'add');
        $categoryModel = new MenuCategory();

        $this->view('menu.item-form', [
            'pageTitle'  => 'Add Menu Item',
            'categories' => $categoryModel->all('category_name ASC'),
            'item'       => null,
            'variants'   => [],
            'csrf'       => $this->csrfField(),
        ]);
    }

    public function storeItem(): void
    {
        Auth::requirePermission('menu', 'add');
        $this->verifyCsrf();

        $name = trim($this->input('item_name', ''));
        $categoryId = (int) $this->input('category_id', 0);
        $basePrice = (float) $this->input('base_price', 0);

        if ($name === '' || $categoryId <= 0) {
            $this->redirect('menu/items/create');
            return;
        }

        $imagePath = $this->handleImageUpload();

        $menuItemModel = new MenuItem();
        $itemId = $menuItemModel->insert([
            'category_id'  => $categoryId,
            'item_name'    => $name,
            'description'  => trim($this->input('description', '')) ?: null,
            'base_price'   => $basePrice,
            'image_path'   => $imagePath,
            'is_available' => (int) $this->input('is_available', 1),
            'track_stock'  => (int) $this->input('track_stock', 0),
        ]);

        AuditLogger::log(Auth::id(), 'MENU_ITEM_CREATE', 'menu', "Added menu item: {$name}");
        $this->redirect('menu/items/edit?id=' . $itemId);
    }

    public function editItem(): void
    {
        Auth::requirePermission('menu', 'edit');
        $id = (int) $this->input('id');

        $menuItemModel = new MenuItem();
        $categoryModel = new MenuCategory();
        $materialModel = new RawMaterial();
        $item = $menuItemModel->find($id);
        if (!$item) {
            $this->redirect('menu');
            return;
        }

        $this->view('menu.item-form', [
            'pageTitle'  => 'Edit Menu Item',
            'categories' => $categoryModel->all('category_name ASC'),
            'item'       => $item,
            'variants'   => $menuItemModel->getVariants($id),
            'recipe'     => $menuItemModel->getRecipe($id),
            'materials'  => $materialModel->allOrdered(),
            'csrf'       => $this->csrfField(),
        ]);
    }

    public function updateItem(): void
    {
        Auth::requirePermission('menu', 'edit');
        $this->verifyCsrf();

        $id = (int) $this->input('id');
        $menuItemModel = new MenuItem();
        $existing = $menuItemModel->find($id);
        if (!$existing) {
            $this->redirect('menu');
            return;
        }

        $imagePath = $existing['image_path'];
        if ((int) $this->input('remove_image', 0) === 1 && $imagePath) {
            $this->deleteUploadedImage($imagePath);
            $imagePath = null;
        }
        $newImage = $this->handleImageUpload();
        if ($newImage) {
            if ($imagePath) {
                $this->deleteUploadedImage($imagePath);
            }
            $imagePath = $newImage;
        }

        $menuItemModel->update($id, [
            'category_id'  => (int) $this->input('category_id', $existing['category_id']),
            'item_name'    => trim($this->input('item_name', $existing['item_name'])),
            'description'  => trim($this->input('description', '')) ?: null,
            'base_price'   => (float) $this->input('base_price', $existing['base_price']),
            'image_path'   => $imagePath,
            'is_available' => (int) $this->input('is_available', 0),
            'track_stock'  => (int) $this->input('track_stock', 0),
        ]);

        AuditLogger::log(Auth::id(), 'MENU_ITEM_UPDATE', 'menu', "Updated menu item #{$id}");
        $this->redirect('menu/items/edit?id=' . $id);
    }

    // --- Image upload helpers ---

    private function handleImageUpload(): ?string
    {
        if (empty($_FILES['image']) || $_FILES['image']['error'] === UPLOAD_ERR_NO_FILE) {
            return null;
        }
        if ($_FILES['image']['error'] !== UPLOAD_ERR_OK) {
            return null;
        }

        $allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];
        $mime = mime_content_type($_FILES['image']['tmp_name']);
        if (!isset($allowed[$mime])) {
            return null; // silently ignore unsupported file types
        }
        if ($_FILES['image']['size'] > 3 * 1024 * 1024) {
            return null; // 3MB limit
        }

        $ext = $allowed[$mime];
        $filename = 'menu_' . bin2hex(random_bytes(8)) . '.' . $ext;
        $uploadDir = ROOT_PATH . '/public/uploads/menu/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        if (!move_uploaded_file($_FILES['image']['tmp_name'], $uploadDir . $filename)) {
            return null;
        }

        return 'uploads/menu/' . $filename;
    }

    private function deleteUploadedImage(?string $relativePath): void
    {
        if (!$relativePath) {
            return;
        }
        $fullPath = ROOT_PATH . '/public/' . $relativePath;
        if (is_file($fullPath)) {
            @unlink($fullPath);
        }
    }

    public function toggleItem(): void
    {
        Auth::requirePermission('menu', 'edit');
        $this->verifyCsrf();

        $id = (int) $this->input('id');
        $menuItemModel = new MenuItem();
        $item = $menuItemModel->find($id);
        if ($item) {
            $menuItemModel->update($id, ['is_available' => $item['is_available'] ? 0 : 1]);
            AuditLogger::log(Auth::id(), 'MENU_ITEM_TOGGLE', 'menu', "Item #{$id} available -> " . ($item['is_available'] ? '0' : '1'));
        }
        $this->redirect('menu');
    }

    public function deleteItem(): void
    {
        Auth::requirePermission('menu', 'delete');
        $this->verifyCsrf();

        $id = (int) $this->input('id');
        $menuItemModel = new MenuItem();

        $db = Database::getConnection();
        $usedInOrders = $db->prepare("SELECT COUNT(*) as cnt FROM order_items WHERE menu_item_id = :id");
        $usedInOrders->execute(['id' => $id]);
        $inUse = (int) $usedInOrders->fetch()['cnt'] > 0;

        if ($inUse) {
            // Item has order history — deactivate instead of deleting to preserve records
            $menuItemModel->update($id, ['is_available' => 0]);
            AuditLogger::log(Auth::id(), 'MENU_ITEM_DEACTIVATE', 'menu', "Item #{$id} has order history — deactivated instead of deleted");
        } else {
            $existing = $menuItemModel->find($id);
            if ($existing && $existing['image_path']) {
                $this->deleteUploadedImage($existing['image_path']);
            }
            $menuItemModel->delete($id);
            AuditLogger::log(Auth::id(), 'MENU_ITEM_DELETE', 'menu', "Deleted menu item #{$id}");
        }
        $this->redirect('menu');
    }

    // --- Variants ---

    public function storeVariant(): void
    {
        Auth::requirePermission('menu', 'add');
        $this->verifyCsrf();

        $itemId = (int) $this->input('menu_item_id');
        $name = trim($this->input('variant_name', ''));
        $adjustment = (float) $this->input('price_adjustment', 0);

        if ($itemId > 0 && $name !== '') {
            (new MenuItem())->addVariant($itemId, $name, $adjustment);
            AuditLogger::log(Auth::id(), 'MENU_VARIANT_CREATE', 'menu', "Added variant '{$name}' to item #{$itemId}");
        }
        $this->redirect('menu/items/edit?id=' . $itemId);
    }

    public function deleteVariant(): void
    {
        Auth::requirePermission('menu', 'delete');
        $this->verifyCsrf();

        $variantId = (int) $this->input('id');
        $itemId = (int) $this->input('menu_item_id');
        (new MenuItem())->deleteVariant($variantId);
        AuditLogger::log(Auth::id(), 'MENU_VARIANT_DELETE', 'menu', "Deleted variant #{$variantId}");
        $this->redirect('menu/items/edit?id=' . $itemId);
    }

    // --- Recipe (raw materials consumed per unit sold) ---

    public function storeRecipe(): void
    {
        Auth::requirePermission('menu', 'edit');
        $this->verifyCsrf();

        $itemId = (int) $this->input('menu_item_id');
        $materialId = (int) $this->input('raw_material_id');
        $qty = (float) $this->input('quantity_required', 0);

        if ($itemId > 0 && $materialId > 0 && $qty > 0) {
            (new MenuItem())->addRecipeLine($itemId, $materialId, $qty);
            AuditLogger::log(Auth::id(), 'MENU_RECIPE_UPDATE', 'menu', "Recipe line saved for item #{$itemId}, material #{$materialId}");
        }
        $this->redirect('menu/items/edit?id=' . $itemId);
    }

    public function deleteRecipe(): void
    {
        Auth::requirePermission('menu', 'edit');
        $this->verifyCsrf();

        $recipeId = (int) $this->input('id');
        $itemId = (int) $this->input('menu_item_id');
        (new MenuItem())->deleteRecipeLine($recipeId);
        AuditLogger::log(Auth::id(), 'MENU_RECIPE_DELETE', 'menu', "Deleted recipe line #{$recipeId}");
        $this->redirect('menu/items/edit?id=' . $itemId);
    }
}
