<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>@yield('title', 'Dashboard') - {{ config('app.name') }}</title>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
    <!-- SAM 전역 설정 (FCM 등에서 사용) -->
    <script>
        window.SAM_CONFIG = {
            apiBaseUrl: '{{ config('services.api.base_url', 'https://api.codebridge-x.com') }}',
            apiKey: '{{ config('services.api.key', '') }}',
            appVersion: '{{ config('app.version', '1.0.0') }}',
            debug: {{ config('app.debug') ? 'true' : 'false' }},
        };

        // API 토큰 sessionStorage 동기화 (FCM 등에서 사용)
        @if(session('api_access_token'))
        (function() {
            const token = '{{ session('api_access_token') }}';
            const expiresAt = {{ session('api_token_expires_at', 0) }};
            const now = Math.floor(Date.now() / 1000);

            // 토큰이 유효한 경우에만 저장
            if (expiresAt > now) {
                sessionStorage.setItem('api_access_token', token);
                sessionStorage.setItem('api_token_expires_at', expiresAt);
            } else {
                // 만료된 토큰 정리
                sessionStorage.removeItem('api_access_token');
                sessionStorage.removeItem('api_token_expires_at');
            }
        })();
        @else
        // 세션에 토큰이 없으면 sessionStorage도 정리
        sessionStorage.removeItem('api_access_token');
        sessionStorage.removeItem('api_token_expires_at');
        @endif
    </script>
    <!-- 페이지 로딩 오버레이 스타일 -->
    <style id="page-loader-styles">
        .page-loader-overlay {
            position: fixed;
            inset: 0;
            z-index: 99999;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(8px);
            -webkit-backdrop-filter: blur(8px);
        }
        .page-loader-content {
            text-align: center;
        }
        .page-loader-bar {
            width: 200px;
            height: 4px;
            background: #e5e7eb;
            border-radius: 2px;
            overflow: hidden;
        }
        .page-loader-progress {
            height: 100%;
            background: linear-gradient(90deg, #3b82f6, #8b5cf6);
            border-radius: 2px;
            animation: loader-progress 1.5s ease-in-out infinite;
        }
        @keyframes loader-progress {
            0% { width: 0%; margin-left: 0; }
            50% { width: 60%; margin-left: 20%; }
            100% { width: 0%; margin-left: 100%; }
        }
        .page-loader-text {
            margin-top: 12px;
            font-size: 14px;
            color: #6b7280;
        }
        /* 블러 해제 애니메이션 */
        .page-loader-overlay.fade-out {
            animation: loader-fade-out 0.3s ease-out forwards;
        }
        @keyframes loader-fade-out {
            to {
                opacity: 0;
                visibility: hidden;
            }
        }
        /* select 요소 텍스트-화살표 겹침 방지 */
        select {
            padding-right: 2rem !important;
        }
    </style>
    <!-- 사이드바 + 메뉴 상태 즉시 적용 -->
    <script>
        (function() {
            // 사이드바 접힘 상태
            if (localStorage.getItem('sidebar-collapsed') === 'true') {
                document.documentElement.classList.add('sidebar-is-collapsed');
            }
            // 메뉴 그룹: hidden 상태인 것만 CSS로 숨김
            var style = document.createElement('style');
            style.id = 'menu-group-preload-styles';
            var css = '';
            var iconCss = '';
            for (var i = 0; i < localStorage.length; i++) {
                var key = localStorage.key(i);
                if (key && key.startsWith('menu-group-menu-group-')) {
                    var groupId = key.replace('menu-group-', '');
                    var state = localStorage.getItem(key);
                    if (state === 'hidden') {
                        css += '#' + groupId + '{display:none!important}';
                        iconCss += '#' + groupId + '-icon{transform:rotate(0deg)!important}';
                    }
                }
            }
            if (css || iconCss) {
                style.textContent = css + iconCss;
                document.head.appendChild(style);
            }
            // 스크롤 위치 미리 저장
            window._savedSidebarScroll = localStorage.getItem('sidebar-scroll-top');
            window._savedSidebarScrollBottom = localStorage.getItem('sidebar-scroll-bottom');
        })();
    </script>
    <script src="https://unpkg.com/htmx.org@1.9.10"></script>
    <!-- Alpine.js Plugins (Collapse) - 반드시 Alpine.js 전에 로드 -->
    <script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
    <!-- Alpine.js -->
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
    <!-- HTMX 전역 설정 (HTMX 로드 직후 등록하여 load 트리거보다 먼저 실행) -->
    <script>
        // HTMX 에러 핸들러 (401 세션 만료 / 419 CSRF 만료)
        document.addEventListener('htmx:responseError', function(event) {
            const status = event.detail.xhr.status;

            // 419 CSRF 토큰 만료 → 페이지 새로고침으로 토큰 갱신
            if (status === 419) {
                console.log('[Session] CSRF 토큰 만료, 페이지 새로고침');
                window.location.reload();
                return;
            }

            if (status !== 401) return;

            // 중복 처리 방지
            if (window._sessionRefreshing) return;
            window._sessionRefreshing = true;

            // 원본 요청 정보 저장
            const originalPath = event.detail.pathInfo?.requestPath || window.location.pathname;

            // 세션 갱신 시도 (Remember Token으로 재인증)
            fetch('/auth/refresh-session', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '',
                    'Accept': 'application/json',
                },
                credentials: 'same-origin',
            })
            .then(response => response.json())
            .then(data => {
                window._sessionRefreshing = false;

                if (data.success) {
                    // 세션 갱신 성공 - 페이지 전체 새로고침 (CSRF 토큰도 갱신)
                    console.log('[Session] 세션 갱신 성공, 페이지 새로고침');
                    window.location.reload();
                } else {
                    // 세션 갱신 실패 - 로그인 페이지로 이동
                    redirectToLogin(data.message || '세션이 만료되었습니다. 다시 로그인해주세요.');
                }
            })
            .catch(error => {
                window._sessionRefreshing = false;
                console.error('[Session] 세션 갱신 실패:', error);
                redirectToLogin('세션이 만료되었습니다. 다시 로그인해주세요.');
            });
        });

        // 로그인 페이지로 리다이렉트 (중복 방지 + 명확한 팝업)
        function redirectToLogin(message) {
            if (window._sessionExpiredRedirecting) return;
            window._sessionExpiredRedirecting = true;

            if (typeof Swal !== 'undefined') {
                Swal.fire({
                    icon: 'warning',
                    title: '세션 만료',
                    text: message,
                    confirmButtonText: '로그인 페이지로 이동',
                    allowOutsideClick: false,
                    allowEscapeKey: false,
                    customClass: {
                        popup: 'rounded-xl shadow-2xl border-0',
                        title: 'text-gray-900 font-semibold',
                        htmlContainer: 'text-gray-600',
                        confirmButton: 'bg-blue-600 hover:bg-blue-700 text-white font-medium px-5 py-2.5 rounded-lg transition-colors',
                    },
                    buttonsStyling: false,
                }).then(() => {
                    window.location.href = '/login';
                });
            } else {
                alert(message);
                window.location.href = '/login';
            }
        }

        document.addEventListener('htmx:configRequest', (event) => {
            // CSRF 토큰 설정
            const csrfToken = document.querySelector('meta[name="csrf-token"]');
            if (csrfToken) {
                event.detail.headers['X-CSRF-TOKEN'] = csrfToken.getAttribute('content');
            }

            // 페이지네이션 per_page 값 적용 (쿠키에서 읽기)
            if (event.detail.parameters && 'per_page' in event.detail.parameters) {
                const getCookieValue = (name) => {
                    const nameEQ = name + "=";
                    const ca = document.cookie.split(';');
                    for (let i = 0; i < ca.length; i++) {
                        let c = ca[i].trim();
                        if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length);
                    }
                    return null;
                };
                const savedPerPage = getCookieValue('pagination_per_page') || '10';
                event.detail.parameters['per_page'] = savedPerPage;

                // perPageInput hidden input도 동기화
                const perPageInput = document.getElementById('perPageInput');
                if (perPageInput) {
                    perPageInput.value = savedPerPage;
                }
            }
        });

        // HTMX 페이지 전환 후 페이지별 스크립트 초기화 (hx-boost 네비게이션용)
        document.addEventListener('htmx:afterSettle', function(event) {
            // main-content 교체 시에만 처리
            if (event.detail.target && event.detail.target.id === 'main-content') {
                initPageScripts();
            }
        });

        // 페이지별 스크립트 초기화 함수
        function initPageScripts() {
            const path = window.location.pathname;

            // /menus 페이지: SortableJS 및 필터 폼 초기화
            if (path === '/menus' || path.startsWith('/menus/')) {
                // SortableJS 초기화 (테이블 로드 후)
                if (typeof initMenuSortable === 'function') {
                    setTimeout(() => initMenuSortable(), 100);
                }
                // 필터 폼 이벤트 리스너 재연결
                const filterForm = document.getElementById('filterForm');
                if (filterForm && !filterForm._htmxInitialized) {
                    filterForm.addEventListener('submit', function(e) {
                        e.preventDefault();
                        htmx.trigger('#menu-table', 'filterSubmit');
                    });
                    filterForm._htmxInitialized = true;
                }
            }
        }
    </script>
    <!-- SweetAlert2 -->
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
    @stack('styles')
</head>
<body class="bg-gray-100 no-transition">
    <!-- 페이지 로딩 오버레이 -->
    <div id="page-loader" class="page-loader-overlay">
        <div class="page-loader-content">
            <div class="page-loader-bar">
                <div class="page-loader-progress"></div>
            </div>
            <div class="page-loader-text">Loading...</div>
        </div>
    </div>

    <div class="flex h-screen overflow-hidden" id="app-container">
        <!-- 모바일 사이드바 백드롭 (lg 미만에서만 동작) -->
        <div id="sidebar-backdrop"
             class="fixed inset-0 bg-black/50 z-40 hidden lg:hidden"
             onclick="closeMobileSidebar()">
        </div>

        <!-- Sidebar -->
        @include('partials.sidebar')

        <!-- Main Content Area -->
        <div id="main-content" class="flex-1 flex flex-col overflow-hidden min-w-0">
            <!-- Header -->
            @include('partials.header')

            <!-- Page Content -->
            <main class="flex-1 overflow-y-auto bg-gray-100 p-6">
                @yield('content')
            </main>
        </div>
    </div>

    <!-- API 인증 모달 (전역) -->
    @include('dev-tools.partials.auth-modal')

    <!-- 전역 컨텍스트 메뉴 -->
    @include('components.context-menu')

    <!-- 테넌트 정보 모달 -->
    @include('components.tenant-modal')

    <!-- 사용자 정보 모달 -->
    @include('components.user-modal')

    <script src="{{ asset('js/pagination.js') }}"></script>
    <script src="{{ asset('js/table-sort.js') }}"></script>
    <script src="{{ asset('js/context-menu.js') }}"></script>
    <script src="{{ asset('js/tenant-modal.js') }}"></script>
    <script src="{{ asset('js/user-modal.js') }}"></script>
    <!-- FCM Push Notification (Capacitor 앱에서만 동작) -->
    <script src="{{ asset('js/fcm.js') }}"></script>
    <!-- SortableJS (메뉴 관리 등 드래그 앤 드롭용) -->
    <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"></script>
    <script src="{{ asset('js/menu-sortable.js') }}"></script>

    <!-- SweetAlert2 공통 함수 (Tailwind 테마) -->
    <script>
        // Tailwind 커스텀 클래스
        const SwalTailwind = Swal.mixin({
            customClass: {
                popup: 'rounded-xl shadow-2xl border-0',
                title: 'text-gray-900 font-semibold',
                htmlContainer: 'text-gray-600',
                confirmButton: 'bg-blue-600 hover:bg-blue-700 text-white font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-blue-300',
                cancelButton: 'bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-gray-100',
                denyButton: 'bg-red-600 hover:bg-red-700 text-white font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-red-300',
                actions: 'gap-3',
            },
            buttonsStyling: false,
        });

        // Toast (스낵바) - 우상단 알림
        const Toast = Swal.mixin({
            toast: true,
            position: 'top-end',
            showConfirmButton: false,
            timer: 3000,
            timerProgressBar: true,
            customClass: {
                popup: 'rounded-lg shadow-lg',
            },
            didOpen: (toast) => {
                toast.onmouseenter = Swal.stopTimer;
                toast.onmouseleave = Swal.resumeTimer;
            }
        });

        /**
         * 토스트 알림 표시
         * @param {string} message - 메시지
         * @param {string} type - 'success' | 'error' | 'warning' | 'info'
         * @param {number} timer - 표시 시간 (ms), 기본 3000
         */
        function showToast(message, type = 'info', timer = 3000) {
            Toast.fire({
                icon: type,
                title: message,
                timer: timer,
            });
        }

        /**
         * 확인 모달 표시
         * @param {string} message - 확인 메시지
         * @param {Function} onConfirm - 확인 시 콜백
         * @param {Object} options - 추가 옵션
         */
        function showConfirm(message, onConfirm, options = {}) {
            const defaultOptions = {
                title: options.title || '확인',
                icon: options.icon || 'question',
                confirmButtonText: options.confirmText || '확인',
                cancelButtonText: options.cancelText || '취소',
                showCancelButton: true,
                reverseButtons: true,
            };

            SwalTailwind.fire({
                ...defaultOptions,
                html: message,
            }).then((result) => {
                if (result.isConfirmed && typeof onConfirm === 'function') {
                    onConfirm();
                }
            });
        }

        /**
         * 삭제 확인 모달 (위험 스타일)
         * @param {string} itemName - 삭제할 항목명
         * @param {Function} onConfirm - 확인 시 콜백
         */
        function showDeleteConfirm(itemName, onConfirm) {
            SwalTailwind.fire({
                title: '삭제 확인',
                html: `<span class="text-red-600 font-medium">"${itemName}"</span>을(를) 삭제하시겠습니까?`,
                icon: 'warning',
                showCancelButton: true,
                confirmButtonText: '삭제',
                cancelButtonText: '취소',
                reverseButtons: true,
                customClass: {
                    popup: 'rounded-xl shadow-2xl border-0',
                    title: 'text-gray-900 font-semibold',
                    htmlContainer: 'text-gray-600',
                    confirmButton: 'bg-red-600 hover:bg-red-700 text-white font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-red-300',
                    cancelButton: 'bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-gray-100',
                    actions: 'gap-3',
                },
                buttonsStyling: false,
            }).then((result) => {
                if (result.isConfirmed && typeof onConfirm === 'function') {
                    onConfirm();
                }
            });
        }

        /**
         * 영구 삭제 확인 모달 (매우 위험)
         * @param {string} itemName - 삭제할 항목명
         * @param {Function} onConfirm - 확인 시 콜백
         */
        function showPermanentDeleteConfirm(itemName, onConfirm) {
            SwalTailwind.fire({
                title: '⚠️ 영구 삭제',
                html: `<span class="text-red-600 font-bold">"${itemName}"</span>을(를) 영구 삭제하시겠습니까?<br><br><span class="text-sm text-gray-500">이 작업은 되돌릴 수 없습니다!</span>`,
                icon: 'error',
                showCancelButton: true,
                confirmButtonText: '영구 삭제',
                cancelButtonText: '취소',
                reverseButtons: true,
                customClass: {
                    popup: 'rounded-xl shadow-2xl border-0',
                    title: 'text-red-600 font-bold',
                    htmlContainer: 'text-gray-600',
                    confirmButton: 'bg-red-600 hover:bg-red-700 text-white font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-red-300',
                    cancelButton: 'bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium px-5 py-2.5 rounded-lg transition-colors focus:ring-4 focus:ring-gray-100',
                    actions: 'gap-3',
                },
                buttonsStyling: false,
            }).then((result) => {
                if (result.isConfirmed && typeof onConfirm === 'function') {
                    onConfirm();
                }
            });
        }

        /**
         * 성공 알림 모달
         * @param {string} message - 메시지
         * @param {Function} onClose - 닫기 후 콜백 (선택)
         */
        function showSuccess(message, onClose = null) {
            SwalTailwind.fire({
                title: '완료',
                text: message,
                icon: 'success',
                confirmButtonText: '확인',
            }).then(() => {
                if (typeof onClose === 'function') {
                    onClose();
                }
            });
        }

        /**
         * 에러 알림 모달
         * @param {string} message - 에러 메시지
         */
        function showError(message) {
            SwalTailwind.fire({
                title: '오류',
                text: message,
                icon: 'error',
                confirmButtonText: '확인',
            });
        }
    </script>

    <!-- 사이드바 토글 스크립트 -->
    <script>
        // 사이드바 상태 관리
        const SIDEBAR_STATE_KEY = 'sidebar-collapsed';

        function toggleSidebar() {
            const sidebar = document.getElementById('sidebar');
            const html = document.documentElement;
            const isCollapsed = sidebar.classList.contains('sidebar-collapsed') || html.classList.contains('sidebar-is-collapsed');

            if (isCollapsed) {
                // 펼치기
                sidebar.classList.remove('sidebar-collapsed');
                html.classList.remove('sidebar-is-collapsed');
                localStorage.setItem(SIDEBAR_STATE_KEY, 'false');
            } else {
                // 접기
                sidebar.classList.add('sidebar-collapsed');
                html.classList.add('sidebar-is-collapsed');
                localStorage.setItem(SIDEBAR_STATE_KEY, 'true');
            }
        }

        // 페이지 로드 시 저장된 사이드바 상태 복원 (클래스 동기화)
        document.addEventListener('DOMContentLoaded', function() {
            const sidebar = document.getElementById('sidebar');
            const html = document.documentElement;
            const savedState = localStorage.getItem(SIDEBAR_STATE_KEY);

            if (savedState === 'true') {
                sidebar.classList.add('sidebar-collapsed');
                html.classList.add('sidebar-is-collapsed');
            } else {
                sidebar.classList.remove('sidebar-collapsed');
                html.classList.remove('sidebar-is-collapsed');
            }
        });
    </script>

    <!-- API 인증 스크립트 (전역) -->
    @include('dev-tools.partials.auth-scripts')

    <!-- 헤더 API 인증 상태 동기화 -->
    <script>
    (function() {
        function updateHeaderAuthBtn() {
            const btn = document.getElementById('header-api-auth-btn');
            if (!btn) return;
            const dot = btn.querySelector('.dev-tools-auth-dot');
            const label = btn.querySelector('.dev-tools-auth-status');
            const isAuth = window.DevToolsAuth && DevToolsAuth.isAuthenticated();

            if (dot) {
                dot.classList.toggle('bg-green-500', isAuth);
                dot.classList.toggle('bg-gray-300', !isAuth);
            }
            if (label) {
                label.textContent = isAuth ? 'API 인증됨' : 'API 인증';
                label.classList.toggle('text-green-600', isAuth);
                label.classList.toggle('text-gray-500', !isAuth);
            }
            btn.classList.toggle('border-green-300', isAuth);
            btn.classList.toggle('border-gray-300', !isAuth);
        }

        // DevToolsAuth 콜백 등록
        if (window.DevToolsAuth) {
            DevToolsAuth.onAuthChange(updateHeaderAuthBtn);
        }

        // 초기 상태 동기화
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', updateHeaderAuthBtn);
        } else {
            updateHeaderAuthBtn();
        }
    })();
    </script>

    @stack('scripts')
</body>
</html>
