<?php

declare(strict_types=1);

use Config\Roles;

if (! function_exists('admin_effective_lg_idx')) {
    /**
     * 현재 로그인한 관리자가 작업 대상으로 사용하는 지자체 PK.
     * Super admin → admin_selected_lg_idx, 지자체 관리자 → mb_lg_idx, 그 외 null.
     */
    function admin_effective_lg_idx(): ?int
    {
        $level = (int) session()->get('mb_level');
        if ($level === Roles::LEVEL_SUPER_ADMIN) {
            $idx = session()->get('admin_selected_lg_idx');
            return $idx !== null && $idx !== '' ? (int) $idx : null;
        }
        if ($level === Roles::LEVEL_LOCAL_ADMIN) {
            $idx = session()->get('mb_lg_idx');
            return $idx !== null && $idx !== '' ? (int) $idx : null;
        }
        return null;
    }
}

if (! function_exists('get_admin_nav_items')) {
    /**
     * 관리자 상단 메뉴 항목 (DB menu 테이블, admin 타입, 현재 지자체·mb_level 기준, 평면 배열).
     * 지자체 미선택(super admin)이면 빈 배열. 테이블/조회 실패 시에도 빈 배열.
     *
     * 하위 메뉴 포함 트리 구조가 필요하면 get_admin_nav_tree() 사용.
     */
    function get_admin_nav_items(): array
    {
        try {
            $lgIdx = admin_effective_lg_idx();
            if ($lgIdx === null) {
                return [];
            }
            $typeRow = model(\App\Models\MenuTypeModel::class)->getByCode('admin');
            if (! $typeRow) {
                return [];
            }
            $mbLevel = (int) session()->get('mb_level');
            return model(\App\Models\MenuModel::class)->getVisibleByLevel((int) $typeRow->mt_idx, $mbLevel, $lgIdx);
        } catch (\Throwable $e) {
            return [];
        }
    }
}

if (! function_exists('build_menu_tree')) {
    /**
     * menu 평면 배열을 mm_pidx/mm_idx 기준 트리로 변환.
     *
     * @param array<int,object> $items
     * @return array<int,object> 루트 노드 배열
     */
    function build_menu_tree(array $items): array
    {
        $map = [];
        foreach ($items as $item) {
            $item->children = [];
            $map[(int) $item->mm_idx] = $item;
        }
        $roots = [];
        foreach ($map as $id => $item) {
            $pidx = (int) $item->mm_pidx;
            if ($pidx === 0 || ! isset($map[$pidx])) {
                $roots[] = $item;
            } else {
                $map[$pidx]->children[] = $item;
            }
        }
        return $roots;
    }
}

if (! function_exists('flatten_menu_tree')) {
    /**
     * 트리 구조의 메뉴를 상위 → 하위 순으로 평면 배열로 풀어낸다.
     * 관리자 메뉴 목록 화면에서 "부모 바로 아래에 자식"이 나오도록 하기 위한 용도.
     *
     * @param array<int,object> $tree
     * @return array<int,object>
     */
    function flatten_menu_tree(array $tree): array
    {
        $result = [];

        $walk = function ($nodes) use (&$result, &$walk) {
            foreach ($nodes as $node) {
                $children = $node->children ?? [];
                // children 속성은 목록에서 사용하지 않으므로 제거
                unset($node->children);
                $result[] = $node;
                if (! empty($children)) {
                    $walk($children);
                }
            }
        };

        $walk($tree);

        return $result;
    }
}

if (! function_exists('get_admin_nav_tree')) {
    /**
     * 관리자 상단 메뉴 트리 (admin 타입, 현재 지자체·mb_level 기준).
     * 1차 메뉴는 mm_pidx=0, 하위 메뉴는 children 속성으로 접근.
     */
    function get_admin_nav_tree(): array
    {
        $flat = get_admin_nav_items();
        if (empty($flat)) {
            return [];
        }
        return build_menu_tree($flat);
    }
}

if (! function_exists('get_site_nav_tree')) {
    /**
     * 일반 사이트 상단 메뉴 트리 (site 타입, 현재 회원의 지자체·mb_level 기준).
     * 1차 메뉴는 mm_pidx=0, 하위 메뉴는 children 속성으로 접근.
     */
    function get_site_nav_tree(): array
    {
        try {
            $lgIdx = session()->get('mb_lg_idx');
            // 시민 등 지자체 정보가 세션에 없으면 기본 지자체(1) 기준으로 메뉴를 보여 준다.
            if ($lgIdx === null || $lgIdx === '') {
                $lgIdx = 1;
            }
            $typeRow = model(\App\Models\MenuTypeModel::class)->getByCode('site');
            if (! $typeRow) {
                return [];
            }
            $mbLevel = (int) session()->get('mb_level');
            $menuModel = model(\App\Models\MenuModel::class);
            $flat      = $menuModel->getVisibleByLevel((int) $typeRow->mt_idx, $mbLevel, (int) $lgIdx);
            // 현재 지자체에 site 메뉴가 없으면, 기본 지자체(1)의 메뉴를 한 번 복사한 뒤 다시 시도
            if (empty($flat)) {
                $menuModel->copyDefaultsFromLg((int) $typeRow->mt_idx, 1, (int) $lgIdx);
                $flat = $menuModel->getVisibleByLevel((int) $typeRow->mt_idx, $mbLevel, (int) $lgIdx);
            }
            if (empty($flat)) {
                return [];
            }
            return build_menu_tree($flat);
        } catch (\Throwable $e) {
            return [];
        }
    }
}
