<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Models\MenuItemModel;
use App\Models\CategoryModel;
use App\Helpers\ImageUploader;
use App\Helpers\ActivityLogger;
use Core\Request;

final class MenuItemController extends BaseController
{
    private MenuItemModel $model;
    private CategoryModel $catModel;
    private ImageUploader $uploader;

    public function __construct()
    {
        parent::__construct();
        $this->model    = new MenuItemModel();
        $this->catModel = new CategoryModel();
        $this->uploader = new ImageUploader('items');
    }

    // ── List ──────────────────────────────────────────────────────────────────

    public function index(array $params = []): void
    {
        $this->requirePermission('menu.view');

        $page    = $this->currentPage();
        $filters = [
            'category_id'  => Request::get('category_id', ''),
            'search'       => Request::get('search', ''),
            'is_available' => Request::get('is_available', ''),
        ];

        $items      = $this->model->all($page, ITEMS_PER_PAGE, $filters);
        $total      = $this->model->count($filters);
        $categories = $this->catModel->activeList();

        $this->view('menu.items.index', [
            'pageTitle'   => 'Menu Items',
            'breadcrumbs' => ['Menu Items' => null],
            'items'       => $items,
            'total'       => $total,
            'page'        => $page,
            'filters'     => $filters,
            'categories'  => $categories,
        ]);
    }

    // ── Create Form ───────────────────────────────────────────────────────────

    public function create(array $params = []): void
    {
        $this->requirePermission('menu.create');

        $this->view('menu.items.form', [
            'pageTitle'      => 'Add Menu Item',
            'breadcrumbs'    => ['Menu Items' => url('menu'), 'Add Item' => null],
            'item'           => null,
            'groups'         => [],
            'categories'     => $this->catModel->activeList(),
            'currencySymbol' => $this->db->fetchValue("SELECT value FROM settings WHERE key_name='currency_symbol'") ?: 'Rs.',
        ]);
    }

    // ── Store ─────────────────────────────────────────────────────────────────

    public function store(array $params = []): void
    {
        $this->requirePermission('menu.create');
        Request::verifyCsrf();

        $errors = $this->validate();
        if ($errors) {
            $this->flash('error', implode('<br>', $errors));
            $this->redirect('/menu/create');
        }

        $name      = Request::str('name');
        $slug      = $this->uniqueSlug(slugify($name));
        $imagePath = null;

        $file = Request::file('item_image');
        if ($file) {
            $result = $this->uploader->upload($file);
            if (!$result['success']) {
                $this->flash('error', $result['error']);
                $this->redirect('/menu/create');
            }
            $imagePath = $result['path'];
        }

        $itemId = $this->model->create([
            'category_id'  => Request::int('category_id'),
            'name'         => $name,
            'slug'         => $slug,
            'description'  => Request::str('description'),
            'base_price'   => Request::float('base_price'),
            'item_image'   => $imagePath,
            'is_available' => Request::bool('is_available', true) ? 1 : 0,
            'sort_order'   => Request::int('sort_order', 0),
            'created_by'   => \Core\Auth::id(),
        ]);

        $groups = $_POST['groups'] ?? [];
        if ($groups) {
            $this->model->saveChoiceGroups($itemId, $groups);
        }

        ActivityLogger::created('menu_item', $itemId, $name);
        $this->flash('success', "Menu item <strong>{$name}</strong> created successfully.");
        $this->redirect('/menu');
    }

    // ── Edit Form ─────────────────────────────────────────────────────────────

    public function edit(array $params = []): void
    {
        $this->requirePermission('menu.edit');

        $item = $this->model->find((int)$params['id']);
        if (!$item) {
            $this->flash('error', 'Menu item not found.');
            $this->redirect('/menu');
        }

        $this->view('menu.items.form', [
            'pageTitle'      => 'Edit Menu Item',
            'breadcrumbs'    => ['Menu Items' => url('menu'), 'Edit' => null],
            'item'           => $item,
            'groups'         => $this->model->getChoiceGroups($item['id']),
            'categories'     => $this->catModel->activeList(),
            'currencySymbol' => $this->db->fetchValue("SELECT value FROM settings WHERE key_name='currency_symbol'") ?: 'Rs.',
        ]);
    }

    // ── Update ────────────────────────────────────────────────────────────────

    public function update(array $params = []): void
    {
        $this->requirePermission('menu.edit');
        Request::verifyCsrf();

        $id   = (int)$params['id'];
        $item = $this->model->find($id);
        if (!$item) {
            $this->flash('error', 'Menu item not found.');
            $this->redirect('/menu');
        }

        $errors = $this->validate($id);
        if ($errors) {
            $this->flash('error', implode('<br>', $errors));
            $this->redirect("/menu/{$id}/edit");
        }

        $name      = Request::str('name');
        $slug      = $this->uniqueSlug(slugify($name), $id);
        $imagePath = $item['item_image'];

        $file = Request::file('item_image');
        if ($file) {
            $result = $this->uploader->upload($file);
            if (!$result['success']) {
                $this->flash('error', $result['error']);
                $this->redirect("/menu/{$id}/edit");
            }
            if ($imagePath) $this->uploader->delete($imagePath);
            $imagePath = $result['path'];
        }

        if (Request::post('remove_image') === '1' && $imagePath) {
            $this->uploader->delete($imagePath);
            $imagePath = null;
        }

        $this->model->update($id, [
            'category_id'  => Request::int('category_id'),
            'name'         => $name,
            'slug'         => $slug,
            'description'  => Request::str('description'),
            'base_price'   => Request::float('base_price'),
            'item_image'   => $imagePath,
            'is_available' => Request::bool('is_available', true) ? 1 : 0,
            'sort_order'   => Request::int('sort_order', 0),
        ]);

        $this->model->saveChoiceGroups($id, $_POST['groups'] ?? []);

        ActivityLogger::updated('menu_item', $id, $name);
        $this->flash('success', "Menu item <strong>{$name}</strong> updated successfully.");
        $this->redirect('/menu');
    }

    // ── Delete ────────────────────────────────────────────────────────────────

    public function delete(array $params = []): void
    {
        $this->requirePermission('menu.delete');
        Request::verifyCsrf();

        $id   = (int)$params['id'];
        $item = $this->model->find($id);
        if (!$item) {
            $this->flash('error', 'Item not found.');
            $this->redirect('/menu');
        }

        if ($item['item_image']) $this->uploader->delete($item['item_image']);

        $this->model->delete($id);
        ActivityLogger::deleted('menu_item', $id, $item['name']);
        $this->flash('success', 'Menu item deleted successfully.');
        $this->redirect('/menu');
    }

    // ── Toggle ────────────────────────────────────────────────────────────────

    public function toggle(array $params = []): void
    {
        $this->requirePermission('menu.edit');
        Request::verifyCsrf();

        $id = (int)$params['id'];
        if (!$this->model->find($id)) {
            $this->json(['success' => false, 'message' => 'Item not found.']);
        }

        $menuItem = $this->model->find($id);
        $newState = $this->model->toggle($id);
        ActivityLogger::toggled('menu_item', $id, $menuItem['name'] ?? '', $newState);
        $this->json(['success' => true, 'message' => 'Status updated.', 'active' => $newState]);
    }

    // ── Internals ─────────────────────────────────────────────────────────────

    private function validate(int $excludeId = 0): array
    {
        $errors = [];
        $name   = Request::str('name');

        if (!$name)                         $errors[] = 'Item name is required.';
        elseif (mb_strlen($name) > 150)     $errors[] = 'Item name must not exceed 150 characters.';

        if (!Request::int('category_id'))   $errors[] = 'Please select a category.';

        $price = Request::float('base_price');
        if ($price < 0)                     $errors[] = 'Price cannot be negative.';

        if ($name && $this->model->slugExists(slugify($name), $excludeId)) {
            $errors[] = 'An item with this name already exists.';
        }

        return $errors;
    }

    private function uniqueSlug(string $slug, int $excludeId = 0): string
    {
        $original = $slug;
        $i        = 1;
        while ($this->model->slugExists($slug, $excludeId)) {
            $slug = $original . '-' . $i++;
        }
        return $slug;
    }
}
