<?php
declare(strict_types=1);

namespace App\Models;

use App\Helpers\FileHandler;
use App\Lib\Database;
use App\Models\{UserSession};
use App\Util\{Helper, Locate};
use WebPConvert\WebPConvert;

class Menu
{
    protected $db;
    protected Helper $helper;
    private string $tableName = 'restaurant';

    public function __construct()
    {
        $this->db = Database::connectDB();
        $this->helper = new Helper;
    }

    public function getById(int $menuId, int $restaurantId, string $selection = '*')
    {
        $stmt = $this->db->fetch("SELECT {$selection} FROM {$this->tableName}_menu WHERE menu_id = ? AND restaurant_id = ? LIMIT 1", $menuId, $restaurantId);
        return $stmt;
    }

    public function getBySlug(string $slug, int $restaurantId, string $selection = '*')
    {
        $stmt = $this->db->fetch("SELECT {$selection} FROM {$this->tableName}_menu WHERE menu_slug = ? AND restaurant_id = ? LIMIT 1", $slug, $restaurantId);
        return $stmt;
    }

    public function getBySearching(string $searching, int $restaurantId, string $selection = '*')
    {
        $stmt = $this->db->fetchAll("SELECT {$selection} FROM {$this->tableName}_menu WHERE restaurant_id = ? AND menu_title LIKE ?", $restaurantId, "%{$searching}%");
        return $stmt;
    }

    public function getLastSorting(int $restaurantId)
    {
        $stmt = $this->db->fetch("SELECT menu_sorting AS sorting FROM {$this->tableName}_menu WHERE restaurant_id = ? ORDER BY menu_sorting DESC LIMIT 1", $restaurantId);
        return $stmt;
    }

    public function isExist(string $menu_name, int $restaurant_id)
    {
        $stmt = $this->db->query("SELECT menu_id FROM {$this->tableName}_menu WHERE restaurant_id = ? AND menu_title = ? LIMIT 1", $restaurant_id, $menu_name);
        return $stmt->rowCount() > 0;
    }

    public function isNameUsed(int $menu_id, int $restaurant_id, string $menu_name)
    {
        $stmt = $this->db->query("SELECT menu_id FROM {$this->tableName}_menu WHERE restaurant_id = ? AND menu_title = ? AND menu_id != ? LIMIT 1", $restaurant_id, $menu_name, $menu_id);
        return $stmt->rowCount() > 0;
    }

    public function getAll(int $restaurantId, string $filterBy = 'all', $selection = '*')
    {
        if($filterBy === 'all'){
            $query = " AND menu_id != '@' ";
        }

        if($filterBy === 'available'){
            $query = " AND menu_status = 'available' ";
        }

        if($filterBy === 'unavailable'){
            $query = " AND menu_status = 'unavailable' ";
        }

        if($filterBy === 'vegetarian'){
            $query = " AND menu_type = 'vegan' ";
        }

        if($filterBy === 'non-vegetarian'){
            $query = " AND menu_type = 'non_vegan' ";
        }

        if($filterBy === 'others' || $filterBy === 'mixed'){
            $query = " AND menu_type = 'mixed' ";
        }

        $stmt = $this->db->fetchAll("SELECT {$selection} FROM {$this->tableName}_menu WHERE restaurant_id = ? {$query} ORDER BY menu_sorting ASC", $restaurantId);
        return $stmt;
    }

    public function countAllMenuDishes(int $restaurantId): object|array
    {
        $stmt = $this->db->query("SELECT
        (SELECT COUNT(menu_id) FROM {$this->tableName}_menu WHERE restaurant_id = ?) AS menu_count,
        (SELECT COUNT(dish_id) FROM {$this->tableName}_dish WHERE restaurant_id = ?) AS dish_count", $restaurantId, $restaurantId);
        $data = $stmt->fetch();
        return ['menu' => $data->menu_count, 'dishes' => $data->dish_count];
    }

    public function addMenu(array $data, int $restaurant_id): void
    {
        $menuSlug = Helper::slugify($data['name']);
        $menuSorting = $this->getLastSorting($restaurant_id)->sorting ?? 0;
        $this->db->query("INSERT INTO {$this->tableName}_menu", [
            "menu_id" => NULL,
            "restaurant_id" => $restaurant_id,
            "menu_title" => $data['name'],
            "menu_slug" => $menuSlug,
            "menu_type" => $data['type'],
            "menu_sorting" => $menuSorting + 1
        ]);
    }

    public function setMenu(array $data, int $restaurant_id): void
    {
        $menuSlug = Helper::slugify($data['name']);
        $menuStatus = $data['toggle'] == 'available' ? 'available' : 'unavailable';

        $this->db->query("UPDATE {$this->tableName}_menu SET
        menu_title = ?,
        menu_slug = ?,
        menu_type = ?,
        menu_status = ?
        WHERE menu_id = ? AND restaurant_id = ? ", $data['name'], $menuSlug, $data['type'], $menuStatus, (int) $data['menu_id'], $restaurant_id);
    }

    public function arrangeMenu(array $menuData, int $restaurant_id): void
    {

        foreach($menuData as $val){
            $this->db->query("UPDATE {$this->tableName}_menu SET
            menu_sorting = ?
            WHERE menu_id = ? AND restaurant_id = ? ", $val['menu_sort'], (int) $val['menu_id'], $restaurant_id);
        }
    }

    public function bulkStatus(int $restaurant_id, array $menuArray, string $action)
    {
        $menuIds = implode(',', $menuArray);
        $this->db->query("UPDATE {$this->tableName}_menu SET menu_status = ? WHERE menu_id IN ({$menuIds}) AND restaurant_id = ?", $action, $restaurant_id);
    }

    public function bulkDelete(int $restaurant_id, array $menuArray): void
    {
        foreach($menuArray as $val){
            $menuId = (int) $val;
            $this->deleteMenu($menuId, $restaurant_id);
        }
    }

    public function deleteMenu(int $menuId, int $restaurantId): void
    {
        $this->db->transaction(function ($database) use ($menuId, $restaurantId) {
            $menuSorting = $this->getById($menuId, $restaurantId, 'menu_sorting')->menu_sorting ?? 0;
            $database->query("DELETE FROM {$this->tableName}_menu WHERE menu_id = ? AND restaurant_id = ?", $menuId, $restaurantId);
            $database->query("UPDATE {$this->tableName}_menu SET menu_sorting = menu_sorting - 1 WHERE menu_sorting > ? AND restaurant_id = ?", $menuSorting, $restaurantId);
            $database->query("UPDATE {$this->tableName}_dish SET menu_id = 0 WHERE menu_id = ? AND restaurant_id = ?", $menuId, $restaurantId);
        });
    }
}
