<?php
/** @var string $title */
require_once __DIR__ . '/_helpers.php';
require_once __DIR__ . '/_settings_links.php';
$hasRescue = $hasRescue ?? false;
$hasCurrent = $hasCurrent ?? false;
$rescueAddr = $rescueAddr ?? null;
$currentAddr = $currentAddr ?? null;
$currentPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
$dashboardActive = $currentPath === '/' || $currentPath === '/dashboard';
$statisticsActive = $currentPath === '/statistics';
$animalsActive = $currentPath === '/animals' || str_starts_with($currentPath, '/animal');
$adminActive = str_starts_with($currentPath, '/admin');
$directoryActive = str_starts_with($currentPath, '/directory');
$careRoundActive = str_starts_with($currentPath, '/care-round');
$agendaActive = str_starts_with($currentPath, '/agenda');
$accountingActive = str_starts_with($currentPath, '/accounting');
$settingsActive = str_starts_with($currentPath, '/settings');
$settingsMenuLinks = settingsNavigationLinks();
$currentUser = Auth::user();
$pageName = trim((string)($title ?? ''));
$documentTitle = $pageName !== '' ? $pageName . ' — Globinours' : 'Globinours';
$pageDescription = trim((string)($pageDescription ?? ''));
if ($pageDescription === '') {
    $pageDescription = match (true) {
        $dashboardActive => t('meta.dashboard'),
        $statisticsActive => t('meta.statistics'),
        $adminActive => t('meta.administrative'),
        $animalsActive => t('meta.animals'),
        default => t('meta.default'),
    };
}
?>
<!doctype html>
<html lang="<?= h(I18n::locale()) ?>">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><?= h($documentTitle) ?></title>
    <meta name="description" content="<?= h($pageDescription) ?>">
    <meta name="application-name" content="Globinours">
    <meta name="robots" content="noindex, nofollow">
    <meta name="theme-color" content="#206bc4">
    <meta name="csrf-token" content="<?= h(Auth::csrf()) ?>">
    <link rel="icon" href="/favicon.ico" sizes="any">
    <link rel="manifest" href="/manifest.webmanifest">
    <link rel="stylesheet" href="/assets/mobile.css">

    <link rel="stylesheet" href="/assets/vendor/tabler/tabler.min.css">
    <link rel="stylesheet" href="/assets/vendor/flatpickr/flatpickr.min.css">
    <link rel="stylesheet" href="/assets/app-shell.css">

    <!-- Chart.js (pour les courbes poids) -->
    <script src="/assets/vendor/chartjs/chart.umd.min.js"></script>
</head>

<body>
    <div class="page">
        <?php require __DIR__ . '/_layout_topbar.php'; ?>
        <div class="page-wrapper">
            <div class="page-header d-print-none">
                <div class="container-xl">
                    <h2 class="page-title"><?= htmlspecialchars($title ?? '', ENT_QUOTES) ?></h2>
                </div>
            </div>

            <div class="page-body">
                <div class="container-xl">
                    <?php require $viewFile; ?>
                </div>
            </div>
            <?php require __DIR__ . '/_layout_footer.php'; ?>
        </div>
    </div>

    <script src="/assets/vendor/tabler/tabler.min.js"></script>

    <link rel="stylesheet" href="/assets/vendor/leaflet/leaflet.css">
    <script src="/assets/vendor/leaflet/leaflet.js"></script>
    <script>
        (function() {
            const rescue = {
                lat: <?= $hasRescue ? (float) $rescueLat : 'null' ?> ,
                lng: <?= $hasRescue ? (float) $rescueLng : 'null' ?> ,
                addr: <?= json_encode($rescueAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
            };

            const cur = {
                lat: <?= $hasCurrent ? (float) $currentLat : 'null' ?> ,
                lng: <?= $hasCurrent ? (float) $currentLng : 'null' ?> ,
                addr: <?= json_encode($currentAddr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
            };

            const el = document.getElementById('mapJourney');
            if (!el || typeof L === 'undefined') return;

            const fallback = [48.5, -4.3];

            // icônes “pastille” colorées
            const iconRescue = L.divIcon({
                className: '',
                iconSize: [18, 18],
                iconAnchor: [9, 9],
                html: '<div class="twix-pin rescue" title="' + <?= json_encode(t('map.rescue'),
                    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> +'"></div>'
            });

            const iconCurrent = L.divIcon({
                className: '',
                iconSize: [18, 18],
                iconAnchor: [9, 9],
                html: '<div class="twix-pin current" title="' + <?= json_encode(t('map.current'),
                    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> +'"></div>'
            });

            const map = L.map('mapJourney', {
                scrollWheelZoom: false
            });

            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                attribution: '&copy; <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a>'
            }).addTo(map);

            const pts = [];

            // helper anti XSS + joli rendu
            const esc = (s) => String(s ?? '')
                .replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;')
                .replaceAll('"', '&quot;').replaceAll("'", "&#039;");
            const safePopup = (label, address) => {
                const box = document.createElement('div');
                const strong = document.createElement('strong');
                strong.textContent = label;
                box.append(strong, document.createElement('br'), document.createTextNode(address || '—'));
                return box;
            };

            if (rescue.lat !== null && rescue.lng !== null) {
                const p = [rescue.lat, rescue.lng];
                pts.push(p);
                L.marker(p, {
                        icon: iconRescue
                    })
                    .addTo(map)
                    .bindPopup(safePopup( <?= json_encode(t('map.rescue'), JSON_UNESCAPED_UNICODE |
                        JSON_UNESCAPED_SLASHES) ?> , rescue.addr), {
                        autoPan: false, // <-- stop le déplacement
                        closeButton: false
                    });
            }

            if (cur.lat !== null && cur.lng !== null) {
                const p = [cur.lat, cur.lng];
                pts.push(p);
                L.marker(p, {
                        icon: iconCurrent
                    })
                    .addTo(map)
                    .bindPopup(safePopup( <?= json_encode(t('map.current'), JSON_UNESCAPED_UNICODE |
                        JSON_UNESCAPED_SLASHES) ?> , cur.addr), {
                        autoPan: false, // <-- stop le déplacement
                        closeButton: false
                    });
            }

            if (pts.length === 0) {
                map.setView(fallback, 8);
                L.popup({
                    autoPan: false
                }).setLatLng(fallback).setContent( <?= json_encode(t('map.missing_coordinates'),
                    JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?> ).openOn(map);
            } else if (pts.length === 1) {
                map.setView(pts[0], 14);
            } else {
                // “vol d’oiseau” : ligne + fitBounds avec padding pour éviter les pins collés au bord
                L.polyline(pts, {
                    weight: 3,
                    opacity: 0.8,
                    dashArray: "6 6"
                }).addTo(map);
                map.fitBounds(L.latLngBounds(pts), {
                    padding: [60, 60]
                }); // <-- plus de marge => popup moins au bord
            }

            // Légende (dans la carte)
            const legend = L.control({
                position: 'topright'
            });
            legend.onAdd = function() {
                const div = L.DomUtil.create('div', 'twix-map-legend');
                div.innerHTML = `
        <div class="row"><span class="dot rescue"></span> ${<?= json_encode(t('map.rescue'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>}</div>
        <div class="row"><span class="dot current"></span> ${<?= json_encode(t('map.current'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>}</div>
        <div class="row" style="opacity:.9"><span class="line"></span> ${<?= json_encode(t('map.flight_path'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>}</div>
        `;
                return div;
            };
            legend.addTo(map);

            // Leaflet + tabs : fix affichage
            setTimeout(() => map.invalidateSize(), 200);
        })();

    </script>
    <script src="/assets/vendor/flatpickr/flatpickr.min.js"></script>
    <script src="/assets/vendor/flatpickr/l10n/fr.js"></script>
    <script defer src="/assets/pwa.js"></script>
    <script src="/assets/global-search.js"></script>
    <script>
        const settingsMenu = document.querySelector('.settings-dropdown .dropdown-menu');
        if (settingsMenu) {
            const groupHeaders = [...settingsMenu.children].filter(node => node.classList.contains('dropdown-header'));
            if (groupHeaders.length === 4) {
                const groups = groupHeaders.map(header => {
                    const group = document.createElement('div');
                    group.className = 'settings-menu-group';
                    const nodes = [header];
                    let next = header.nextElementSibling;
                    while (next && !next.classList.contains('dropdown-divider') && !next.classList.contains(
                            'dropdown-header') && next.tagName !== 'FORM') {
                        nodes.push(next);
                        next = next.nextElementSibling;
                    }
                    nodes.forEach(node => group.appendChild(node));
                    return group;
                });
                const logout = settingsMenu.querySelector(':scope > form[action="/logout"]');
                const logoutDivider = logout?.previousElementSibling?.classList.contains('dropdown-divider') ? logout
                    .previousElementSibling : null;
                [...settingsMenu.querySelectorAll(':scope > .dropdown-divider')].forEach((divider, index) => {
                    if (index > 0 && divider !== logoutDivider) divider.remove();
                });
                const columns = document.createElement('div');
                columns.className = 'settings-menu-columns';
                const configuration = document.createElement('div');
                configuration.className = 'settings-menu-column';
                configuration.append(groups[0], groups[1]);
                const administration = document.createElement('div');
                administration.className = 'settings-menu-column';
                administration.append(groups[2], groups[3]);
                columns.append(configuration, administration);
                settingsMenu.insertBefore(columns, logoutDivider || logout || null);
                settingsMenu.classList.add('settings-menu-wide');
            }
        }
        const globinoursPermissions = <?= json_encode(PermissionService::currentPermissions(),
            JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?> ;
        const permissionModuleForPath = path => {
            if (path === '/' || path.startsWith('/dashboard')) return 'dashboard';
            if (path.startsWith('/animal/documents')) return 'medical';
            if (path.startsWith('/animals') || path.startsWith('/animal') || path.startsWith('/litter') || path
                .startsWith('/bonded')) {
                if (['/animal/add-medical', '/animal/medical-status', '/animal/add-treatment',
                        '/animal/add-vaccine', '/animal/death', '/animal/surgery'
                    ].some(prefix => path.startsWith(prefix))) return 'medical';
                return 'animals';
            }
            if (path.startsWith('/care-round')) return 'care';
            if (path.startsWith('/directory')) return 'directory';
            if (path.startsWith('/statistics')) return 'statistics';
            if (path.startsWith('/accounting')) return 'accounting';
            if (path.startsWith('/admin/grants')) return 'grants';
            if (path.startsWith('/admin') || path.startsWith('/documents')) return 'administrative';
            return null;
        };
        const permissionEditPages = new Set(['/animal/new', '/animal/edit', '/animal/death', '/litter/new',
            '/litter/add-existing', '/litter/add-existing/save', '/bonded/new', '/directory/new',
            '/directory/edit', '/care-round/setup'
        ]);
        const permissionAllows = (url, action = 'view') => {
            let path;
            try {
                path = new URL(url, location.origin).pathname;
            } catch {
                return true;
            }
            const module = permissionModuleForPath(path);
            if (!module) return true;
            if (action === 'view' && permissionEditPages.has(path)) action = 'edit';
            return Boolean(globinoursPermissions[module]?.[action]);
        };
        document.querySelectorAll('.page-body form').forEach(form => {
            if ((form.method || 'get').toLowerCase() !== 'post') return;
            if (!permissionAllows(form.action, 'edit')) {
                form.hidden = true;
                form.dataset.permissionHidden = 'true';
            }
        });
        document.querySelectorAll('.page-body a[href]').forEach(link => {
            const raw = link.getAttribute('href') || '';
            if (raw.startsWith('#') || raw.startsWith('javascript:')) return;
            if (!permissionAllows(link.href, 'view')) {
                link.hidden = true;
                link.dataset.permissionHidden = 'true';
            }
        });
        document.querySelectorAll('.page-body [data-bs-target]').forEach(trigger => {
            const target = document.querySelector(trigger.getAttribute('data-bs-target'));
            const actions = target ? [...target.querySelectorAll('form')].map(form => form.action) : [];
            if (actions.length && actions.every(action => !permissionAllows(action, 'edit'))) {
                trigger.hidden = true;
                trigger.dataset.permissionHidden = 'true';
            }
        });
        document.querySelectorAll('.page-body .dropdown-menu').forEach(menu => {
            const available = [...menu.querySelectorAll('a,button,form')].some(item => !item.hidden && item
                .dataset.permissionHidden !== 'true' && !item.closest('[data-permission-hidden="true"]'));
            if (!available) {
                const dropdown = menu.closest('.dropdown');
                if (dropdown) dropdown.hidden = true;
            }
        });
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
        document.querySelectorAll('form[method="post" i]').forEach(form => {
            if (!csrfToken || form.querySelector('input[name="csrf"]')) return;
            const input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'csrf';
            input.value = csrfToken;
            form.appendChild(input);
        });
        const validationMessages = {
            required: <?= json_encode(t('validation.required'), JSON_UNESCAPED_UNICODE) ?> ,
            passwordMin: count => <?= json_encode(t('validation.password_min'), JSON_UNESCAPED_UNICODE) ?>
                .replace(':count', count),
            invalidFormat: <?= json_encode(t('validation.invalid_format'), JSON_UNESCAPED_UNICODE) ?> ,
            checkField: <?= json_encode(t('validation.check_field'), JSON_UNESCAPED_UNICODE) ?>
        };
        document.querySelectorAll('form').forEach(form => {
            if (!form.querySelector('input[type="password"]')) return;
            form.noValidate = true;
            form.addEventListener('submit', event => {
                form.querySelectorAll('.is-invalid').forEach(field => field.classList.remove(
                    'is-invalid'));
                if (form.checkValidity()) return;
                event.preventDefault();
                event.stopPropagation();
                form.querySelectorAll(':invalid').forEach(field => {
                    field.classList.add('is-invalid');
                    let feedback = field.parentElement.querySelector('.invalid-feedback');
                    if (!feedback) {
                        feedback = document.createElement('div');
                        feedback.className = 'invalid-feedback';
                        field.insertAdjacentElement('afterend', feedback);
                    }
                    feedback.textContent = field.validity.valueMissing ? validationMessages
                        .required : field.validity.tooShort ? validationMessages.passwordMin(
                            field.minLength) : field.validity.typeMismatch ? validationMessages
                        .invalidFormat : validationMessages.checkField;
                });
                form.querySelector(':invalid')?.focus();
            });
            form.querySelectorAll('input').forEach(field => field.addEventListener('input', () => field
                .classList.remove('is-invalid')));
        });
        document.querySelectorAll('input[type="date"]').forEach(input => {
            flatpickr(input, {
                locale: <?= json_encode(I18n::locale() === 'fr' ? 'fr' : 'default') ?> ,
                altInput: true,
                altFormat: 'd/m/Y',
                dateFormat: 'Y-m-d',
                allowInput: true,
                disableMobile: true
            });
        });

    </script>
    <script src="/assets/accounting.js"></script>
    <script>
        document.querySelectorAll('select option').forEach(o => {
            const s = o.textContent || '';
            if (s) o.textContent = s.charAt(0).toLocaleUpperCase(document.documentElement.lang || 'fr') + s
                .slice(1);
        });

    </script>
</body>

</html>
