<?php

declare(strict_types=1);

function dental_navigation_public_route_keys(): array
{
    return [
        'appointment-new','appointment-returning','appointment-received','website-page',
        'patient-login','patient-activate','account-activate','patient-logout','patient-portal','patient-record','queue_display',
    ];
}

function dental_navigation_handler_route_keys(): array
{
    return [
        'download_backup','download_installer','download_release','download_document','download_upload',
        'download_inventory_evidence','download_kiosk_launcher','doctor_asset','print_record','calendar',
    ];
}

function dental_navigation_role_codes(): array
{
    return ['super_admin','clinic_admin','receptionist','staff','dentist','dental_assistant','cashier','inventory_officer'];
}

function dental_navigation_route_inventory(): array
{
    $routesFile = DENTAL_ROOT . '/config/routes.php';
    $slugsFile = DENTAL_ROOT . '/config/route_slugs.php';
    $routes = is_file($routesFile) ? require $routesFile : [];
    $slugs = is_file($slugsFile) ? require $slugsFile : [];
    if (!is_array($routes)) $routes = [];
    if (!is_array($slugs)) $slugs = [];

    if (function_exists('task_route_access_requirements')) {
        $requirements = task_route_access_requirements();
    } else {
        $accessFile = DENTAL_ROOT . '/config/route_access.php';
        $requirements = is_file($accessFile) ? require $accessFile : [];
        if (!is_array($requirements)) $requirements = [];
    }
    $workspaces = function_exists('task_workspace_definitions') ? task_workspace_definitions() : [];
    $publicRoutes = array_fill_keys(dental_navigation_public_route_keys(), true);
    $handlerRoutes = array_fill_keys(dental_navigation_handler_route_keys(), true);

    $slugCounts = [];
    foreach ($slugs as $slug) {
        $slug = (string)$slug;
        $slugCounts[$slug] = ($slugCounts[$slug] ?? 0) + 1;
    }

    $fileRoutes = [];
    foreach ($routes as $route => $file) {
        $fileRoutes[(string)$file][] = (string)$route;
    }

    $inventory = [];
    foreach ($routes as $route => $file) {
        $route = (string)$route;
        $file = (string)$file;
        $classification = isset($publicRoutes[$route]) ? 'public' : (isset($handlerRoutes[$route]) ? 'handler' : 'internal');
        $requirement = is_array($requirements[$route] ?? null) ? $requirements[$route] : [];
        $accessRoles = array_values(array_unique(array_map('strval', (array)($requirement['roles'] ?? []))));
        if ($route === 'dashboard') $accessRoles = dental_navigation_role_codes();

        $navigationRoles = [];
        foreach (dental_navigation_role_codes() as $role) {
            $workspace = is_array($workspaces[$role] ?? null) ? $workspaces[$role] : [];
            $pages = array_map('strval', (array)($workspace['pages'] ?? []));
            if (in_array('*', $pages, true) || in_array($route, $pages, true)) $navigationRoles[] = $role;
        }

        $slug = (string)($slugs[$route] ?? '');
        $issues = [];
        if (!is_file($file)) $issues[] = 'Route target file is missing.';
        if ($slug === '') $issues[] = 'Clean URL slug is missing.';
        if ($slug !== '' && ($slugCounts[$slug] ?? 0) > 1) $issues[] = 'Clean URL slug is duplicated.';
        if ($classification === 'internal' && $route !== 'dashboard' && $requirement === []) $issues[] = 'Task View authorization requirement is missing.';
        if ($classification === 'internal' && $accessRoles === [] && $route !== 'dashboard') $issues[] = 'No authorized role is declared.';

        $visibility = $classification === 'public'
            ? 'Public'
            : ($classification === 'handler'
                ? 'Handler / action'
                : ($navigationRoles !== [] ? 'Workspace navigation' : 'Direct / linked'));

        $inventory[] = [
            'route'=>$route,
            'slug'=>$slug,
            'file'=>$file,
            'relative_file'=>str_starts_with($file, DENTAL_ROOT . '/') ? substr($file, strlen(DENTAL_ROOT) + 1) : $file,
            'classification'=>$classification,
            'visibility'=>$visibility,
            'access_roles'=>$accessRoles,
            'navigation_roles'=>$navigationRoles,
            'permission'=>(string)($requirement['permission'] ?? ''),
            'action'=>(string)($requirement['action'] ?? ''),
            'aliases'=>array_values(array_diff((array)($fileRoutes[$file] ?? []), [$route])),
            'issues'=>$issues,
            'ready'=>$issues === [],
        ];
    }

    usort($inventory, static fn(array $a, array $b): int => [$a['classification'],$a['route']] <=> [$b['classification'],$b['route']]);
    return $inventory;
}

function dental_navigation_integrity_snapshot(): array
{
    $rows = dental_navigation_route_inventory();
    $issues = [];
    $counts = [
        'routes'=>count($rows),
        'ready'=>0,
        'blocked'=>0,
        'public'=>0,
        'internal'=>0,
        'handler'=>0,
        'workspace_navigation'=>0,
        'direct_linked'=>0,
    ];

    foreach ($rows as $row) {
        $classification = (string)($row['classification'] ?? 'internal');
        if (isset($counts[$classification])) $counts[$classification]++;
        if (!empty($row['ready'])) $counts['ready']++; else {
            $counts['blocked']++;
            $issues[] = ['route'=>(string)$row['route'], 'issues'=>(array)$row['issues']];
        }
        if (($row['visibility'] ?? '') === 'Workspace navigation') $counts['workspace_navigation']++;
        if (($row['visibility'] ?? '') === 'Direct / linked') $counts['direct_linked']++;
    }

    $canonical = json_encode(['counts'=>$counts,'issues'=>$issues], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    return [
        'ready'=>$counts['blocked'] === 0,
        'counts'=>$counts,
        'issues'=>$issues,
        'rows'=>$rows,
        'fingerprint'=>hash('sha256', is_string($canonical) ? $canonical : ''),
        'generated_at'=>date(DATE_ATOM),
    ];
}

function dental_navigation_session_snapshot(): array
{
    $contextKeys = [
        'task_role','active_role','task_context_role','task_dentist_id','dental_patient_context',
        'active_patient_context','dental_active_clinical_context','cashier_patient_context',
        'dental_viewed_patient_id','dental_selected_visit_id','dental_update_pending_cache',
        'dental_redirect_edges','dental_redirect_loop_detected_at','dental_redirect_loop_pair',
    ];
    $present = [];
    foreach ($contextKeys as $key) {
        if (array_key_exists($key, $_SESSION)) $present[$key] = $_SESSION[$key];
    }
    return [
        'actual_role'=>function_exists('actual_role') ? actual_role() : (string)($_SESSION['user']['role'] ?? ''),
        'active_role'=>function_exists('active_role') ? active_role() : (string)($_SESSION['task_role'] ?? $_SESSION['user']['role'] ?? ''),
        'context'=>$present,
    ];
}

function dental_navigation_reset_current_workspace(): array
{
    $before = array_keys((array)dental_navigation_session_snapshot()['context']);
    if (function_exists('dental_task_context_clear_for_switch')) {
        dental_task_context_clear_for_switch(
            function_exists('active_role') ? active_role() : '',
            function_exists('actual_role') ? actual_role() : ''
        );
    }

    foreach ([
        'task_dentist_id','dental_patient_context','active_patient_context','dental_active_clinical_context',
        'cashier_patient_context','dental_viewed_patient_id','dental_selected_visit_id','dental_update_pending_cache',
        'portal_redirect_target','dental_redirect_edges','dental_redirect_loop_detected_at','dental_redirect_loop_pair',
    ] as $key) unset($_SESSION[$key]);

    if (function_exists('actual_role') && actual_role() === 'super_admin') {
        unset($_SESSION['task_role'], $_SESSION['active_role'], $_SESSION['task_context_role']);
    }
    if (function_exists('setting_request_cache_clear')) setting_request_cache_clear();

    return ['cleared'=>$before, 'remaining'=>array_keys((array)dental_navigation_session_snapshot()['context'])];
}
