<?php

namespace App\Http\Middleware\Prepare;

use Closure;
use Illuminate\Support\Facades\View;
use Spatie\Menu\Laravel\Facades\Menu;
use Spatie\Menu\Laravel\Link;
use Spatie\Menu\Laravel\Html;
use Exception;

class Admin
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle($request, Closure $next)
    {
        $menus = config('menus');

        // 관리자 메뉴 설정
        $routers = $this->routers($menus);

		// 현재 메뉴 위치 조회
        $menus = $this->buildMenu($menus, $routers);

	   	View::share('menus', $menus);

        unset($menus, $routers, $menus);

        return $next($request);
    }

    /**
     * 관리자 메뉴 배열화
     */
    private function routers(array $menus, $arr = [], $parent = null)
    {
        foreach ($menus as $controller => $row) {
            $info = (key($row) == '/' ? current($row) : $row);

            if($parent) {
                $segment = [
                    ADMIN_PATH,
                    $parent,
                    $controller
                ];
            }else{
                $segment = [
                    ADMIN_PATH,
                    $controller
                ];
            }

            $arr[$info[1]] = join(DIRECTORY_SEPARATOR, $segment);
            if (isset($info[5]) && $info[5]) {
                $arr = $this->routers($info[5], $arr, $controller);
            }
        }
        return $arr;
    }

    /**
     * 관리자 메뉴 생성
     */
    private function buildMenu(array $menus, array $routers): \Spatie\Menu\Menu|callable
    {
        $menu = Menu::new();

        $segments = request()->segments();
        foreach ($menus as $row) {
            $info = (key($row) == '/' ? current($row) : $row);
            $router = (array_key_exists($info[1], $routers) ? $routers[$info[1]] : "");

            try {

                $link = Link::to(url($router), (
                    ($info[3] ? Html::raw(sprintf('<i class="%s"></i>', $info[3]))->render() : '') .
                    Html::raw(sprintf('<span class="ps-2">%s</span>', $info[2]))->render()
                ))->addClass('nav-link')->setActive(function () use ($router, $routers, $segments) {
                    $d1 = array_filter($segments);
                    $d2 = array_filter(explode(DIRECTORY_SEPARATOR, $router));
                    $c = count(array_diff($d1, $d2));
                    $e = join(DIRECTORY_SEPARATOR, $d1);

                    if (in_array($e, $routers)) {
                        if ($c == 0 && ($router == $e)) {
                            return true;
                        }
                    } else if (count($d1) == count($d2)) {
                        if ($c == 1) {
                            array_splice($d2, -1, 1);
                            return request()->is(join(DIRECTORY_SEPARATOR, $d2) . '/*');
                        }
                    }
                    return false;
                });

                if (isset($info[5]) && $info[5]) {
                    $id = ('menu_' . $info[1]);

                    $menu->submenu(
                        // 상위 메뉴
                        $link->setAttributes([
                            'data-bs-target' => ('#' . $id),
                            'data-bs-toggle' => 'collapse',
                            'role' => 'button',
                            'aria-expanded' => 'false',
                            'aria-controls' => $id
                        ])->setActive(function () use ($router) {
                            return request()->is($router . '/*');
                        }),

                        // 하위 메뉴
                        Menu::new()
                            ->withoutWrapperTag()
                            ->withoutParentTag()
                            ->html(
                                sprintf('<div id="%s" class="collapse">%s</div>', $id, $this->buildMenu($info[5], $routers))
                            )
                    );
                } else {
                    $menu->add(
                        $link
                    );
                }

                unset($info, $router, $link);

            } catch (Exception) {
                exit('관리자 메뉴 설정 값이 잘못되었습니다.');
            }
        }

        unset($menus, $routers, $segments);

        return $menu->addClass('nav flex-column');
    }
}
