<?php
/**
 * Main Entry Point - Router
 * HanifiAcademy Sales OS - Refactored Version
 */

// Set UTF-8 encoding as default
header('Content-Type: text/html; charset=utf-8');
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' https://app.didar.me; object-src 'none'; frame-ancestors 'self'; base-uri 'self';");

// Load constants first
require_once __DIR__ . '/../app/config/constants.php';

// Start session (only if not already started)
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// PERF: gzip dynamic responses (HTML + JSON) at the PHP layer so compression works even
// when the web server's mod_deflate/brotli is unavailable. ob_gzhandler honors the client's
// Accept-Encoding (unlike zlib.output_compression). Skipped for binary-streaming actions
// (export_run spreadsheet, payment_file receipt) which must not be re-compressed.
$__binaryStreamAction = (isset($_GET['api']) && in_array($_GET['api'], ['export_run', 'payment_file'], true));
if (!$__binaryStreamAction
    && !ini_get('zlib.output_compression')
    && function_exists('ob_gzhandler')
    && !headers_sent()
    && strpos((string)($_SERVER['HTTP_ACCEPT_ENCODING'] ?? ''), 'gzip') !== false) {
    header('Vary: Accept-Encoding');
    ob_start('ob_gzhandler');
}

// Global view helper functions (role checks, etc.)
require_once __DIR__ . '/../app/helpers/functions.php';

// Load Composer autoload
require_once __DIR__ . '/../vendor/autoload.php';

// Bootstrap application
$mockMode = false;
try {
    $app = require __DIR__ . '/../app/bootstrap.php';
    // Make $app available globally for old index.php compatibility
    $GLOBALS['app'] = $app;

    // Initialize Request Logger
    // This logs every backend action/page view except noisy ones
    if (class_exists(\App\Middleware\RequestLogger::class)) {
        $logger = new \App\Middleware\RequestLogger($app->services->audit);
        $logger->handle();
    }

} catch (Exception $e) {
    error_log("Application bootstrap failed: " . $e->getMessage());
    $allowMockUi = in_array(strtolower((string)(getenv('ALLOW_UI_MOCK') ?: '0')), ['1', 'true', 'yes', 'on'], true)
        || isset($_GET['mock_ui']);
    if (!$allowMockUi) {
        if (php_sapi_name() !== 'cli') {
            http_response_code(500);
            die("خطا در راه‌اندازی سیستم. لطفاً با مدیر سیستم تماس بگیرید.");
        }
        throw $e;
    }

    $mockMode = true;
    $_SESSION['user_id'] = $_SESSION['user_id'] ?? 1;
    $_SESSION['role'] = $_SESSION['role'] ?? 'admin';
    $_SESSION['didar_id'] = $_SESSION['didar_id'] ?? 'mock_admin';
    $_SESSION['name'] = $_SESSION['name'] ?? 'Mock Admin';
    $_SESSION['display_name'] = $_SESSION['display_name'] ?? 'Mock Admin';

    $app = (object)[
        'db' => null,
        'repositories' => (object)[],
        'services' => (object)[
            'auth' => new class {
                public function isAuthenticated() { return true; }
                public function isAdmin() { return true; }
                public function isAdminOrCrmSpecialist() { return true; }
                public function isCrmSpecialist() { return false; }
            }
        ],
        'middleware' => (object)[],
    ];
    $GLOBALS['app'] = $app;
}

// Handle logout shortcut (?logout) similar to legacy behaviour
if (isset($_GET['logout'])) {
    // Destroy session and redirect to main page (login/setup will be selected automatically)
    session_destroy();
    header('Location: /');
    exit;
}

// Handle API requests
if (isset($_GET['api'])) {
    $action = $_GET['api'];
    if (!in_array($action, ['export_run', 'payment_file'], true)) {
        header('Content-Type: application/json');
    }

    // PERF: release the PHP session file lock as early as possible so concurrent AJAX
    // requests from the same user run in parallel instead of queueing behind the lock.
    // $_SESSION stays READABLE after this call (controllers still read role/didar_id);
    // only the handful of actions below write to the session, so they keep it open.
    $sessionWritingActions = ['login', 'logout', 'setup_init', 'setup_complete', 'setup_sync', 'resume_sync'];
    if (!in_array($action, $sessionWritingActions, true) && session_status() === PHP_SESSION_ACTIVE) {
        session_write_close();
    }

    try {
        if ($mockMode) {
            $mockPayload = ['status' => 'success', 'mock_mode' => true];
            if ($action === 'get_lookups') {
                echo json_encode($mockPayload + [
                    'lookups' => [
                        'pipeline_stages' => ['items' => [
                            ['value' => 'در حال پیگیری', 'title' => 'در حال پیگیری'],
                            ['value' => 'اتمام', 'title' => 'اتمام'],
                            ['value' => 'معامله ناموفق', 'title' => 'معامله ناموفق'],
                        ]],
                        'allowed_services' => ['items' => [
                            ['value' => 'Mock Product A', 'title' => 'Mock Product A', 'meta_json' => '{"price":10000000,"price_list_code":"MOCK-A"}'],
                            ['value' => 'Mock Product B', 'title' => 'Mock Product B', 'meta_json' => '{"price":15000000,"price_list_code":"MOCK-B"}'],
                        ]],
                        'payment_methods' => ['items' => [
                            ['value' => 'card_to_card', 'title' => 'کارت به کارت'],
                            ['value' => 'cash', 'title' => 'نقد'],
                        ]],
                        'payment_destination_banks' => ['items' => [
                            ['value' => 'melli', 'title' => 'ملی'],
                            ['value' => 'mellat', 'title' => 'ملت'],
                        ]],
                    ]
                ]);
                exit;
            }
            if ($action === 'rbac_current_permissions') {
                echo json_encode($mockPayload + [
                    'role' => 'admin',
                    'capabilities' => ['*'],
                    'scopes' => [],
                ]);
                exit;
            }
            if ($action === 'get_activity_types') {
                echo json_encode($mockPayload + [
                    'types' => [
                        ['Id' => 'mock_call_out', 'Title' => 'تماس خروجی'],
                        ['Id' => 'mock_call_in', 'Title' => 'تماس ورودی'],
                        ['Id' => 'mock_followup', 'Title' => 'پیگیری'],
                    ]
                ]);
                exit;
            }
            if ($action === 'get_notifications') {
                echo json_encode($mockPayload + ['notifications' => [], 'unread_count' => 0]);
                exit;
            }
            if ($action === 'get_notification_count' || $action === 'notification_count') {
                echo json_encode($mockPayload + ['count' => 0, 'unread_count' => 0]);
                exit;
            }
            if ($action === 'check_reminders') {
                echo json_encode($mockPayload + ['notifications' => [], 'count' => 0]);
                exit;
            }
            if ($action === 'get_didar_users') {
                echo json_encode($mockPayload + ['users' => [
                    ['id' => 'mock_admin', 'name' => 'Mock Admin'],
                    ['id' => 'mock_sales_1', 'name' => 'Mock Sales 1'],
                ]]);
                exit;
            }
            if ($action === 'get_products' || $action === 'get_kpi_products') {
                echo json_encode($mockPayload + ['products' => [
                    ['id' => 10, 'name' => 'Mock Product A'],
                    ['id' => 11, 'name' => 'Mock Product B'],
                ]]);
                exit;
            }
            if ($action === 'get_users_list') {
                echo json_encode($mockPayload + [
                    'users' => [
                        ['id' => 1, 'didar_user_id' => 'mock_admin', 'email' => 'admin@mock.local', 'first_name' => 'Mock', 'last_name' => 'Admin', 'display_name' => 'Mock Admin', 'role' => 'admin', 'is_active' => 1],
                        ['id' => 2, 'didar_user_id' => 'mock_sales_1', 'email' => 'sales1@mock.local', 'first_name' => 'Mock', 'last_name' => 'Sales 1', 'display_name' => 'Mock Sales 1', 'role' => 'agent', 'is_active' => 1],
                    ],
                    'master_password_configured' => false
                ]);
                exit;
            }
            if ($action === 'get_dashboard_stats') {
                echo json_encode($mockPayload + ['stats' => ['total_leads' => 0, 'total_deals' => 0, 'won_deals' => 0, 'lost_deals' => 0]]);
                exit;
            }
            if ($action === 'get_leads' || $action === 'get_deals' || $action === 'get_legacy_deals' || $action === 'get_referrals' || $action === 'get_reminders_list') {
                $key = $action === 'get_leads' ? 'leads' : ($action === 'get_deals' || $action === 'get_legacy_deals' ? 'deals' : ($action === 'get_referrals' ? 'referrals' : 'reminders'));
                echo json_encode($mockPayload + [$key => [], 'total' => 0, 'page' => 1, 'per_page' => 20]);
                exit;
            }
            if ($action === 'get_commission_matrix_data') {
                echo json_encode($mockPayload + [
                    'users' => [
                        ['id' => 1, 'display_name' => 'Mock Sales 1', 'role' => 'agent', 'is_active' => 1],
                        ['id' => 2, 'display_name' => 'Mock Sales 2', 'role' => 'agent', 'is_active' => 1],
                    ],
                    'products' => [],
                    'rules' => [],
                    'assignments' => []
                ]);
                exit;
            }
            if ($action === 'save_commission_rule') {
                echo json_encode($mockPayload + ['id' => 999, 'message' => 'Mock: قانون پورسانت ذخیره شد']);
                exit;
            }
            if ($action === 'get_deal_commissions') {
                echo json_encode($mockPayload + [
                    'commissions' => [[
                        'id' => 500,
                        'deal_didar_id' => 'mock_deal_001',
                        'salesperson_name' => 'Mock Sales 1',
                        'ncr_amount' => '10000000.00',
                        'applied_rate_percent' => '2.5000',
                        'calculated_commission' => '275000.00',
                        'status' => 'PENDING_MANAGER_REVIEW',
                    ]]
                ]);
                exit;
            }
            if ($action === 'update_deal_commission_status') {
                echo json_encode($mockPayload + ['message' => 'Mock: وضعیت پورسانت به‌روزرسانی شد']);
                exit;
            }
            if ($action === 'login' || $action === 'get_login_users') {
                echo json_encode($mockPayload + ['users' => [['id' => 1, 'display_name' => 'Mock Admin', 'role' => 'admin']]]);
                exit;
            }
            echo json_encode(['status' => 'error', 'mock_mode' => true, 'message' => 'Mock mode: endpoint unavailable', 'endpoint' => $action]);
            exit;
        }

        // Public endpoints (no auth required)
        if ($action === 'setup_init') {
            $controller = new \App\Controllers\SetupController(
                $app->services->didarApi,
                $app->services->sync,
                $app->repositories->config,
                $app->repositories->user,
                $app->db
            );
            $controller->init();
            exit;
        }
        
        if ($action === 'setup_complete') {
            $controller = new \App\Controllers\SetupController(
                $app->services->didarApi,
                $app->services->sync,
                $app->repositories->config,
                $app->repositories->user,
                $app->db
            );
            $controller->complete();
            exit;
        }
        
        if ($action === 'setup_sync') {
            $controller = new \App\Controllers\SetupController(
                $app->services->didarApi,
                $app->services->sync,
                $app->repositories->config,
                $app->repositories->user,
                $app->db
            );
            $controller->sync();
            exit;
        }

        if ($action === 'get_sync_status') {
            $controller = new \App\Controllers\SetupController(
                $app->services->didarApi,
                $app->services->sync,
                $app->repositories->config,
                $app->repositories->user,
                $app->db
            );
            $controller->getSyncStatus();
            exit;
        }

        if ($action === 'resume_sync') {
            $controller = new \App\Controllers\SetupController(
                $app->services->didarApi,
                $app->services->sync,
                $app->repositories->config,
                $app->repositories->user,
                $app->db
            );
            $controller->resumeSync();
            exit;
        }

        if ($action === 'get_login_users') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth
            );
            $controller->getLoginUsers();
            exit;
        }

        if ($action === 'get_lead_assignment') {
            $controller = new \App\Controllers\IntegrationController(
                $app->repositories->config,
                $app->repositories->person,
                $app->repositories->serviceGovernance
            );
            $controller->getLeadAssignment();
            exit;
        }

        if ($action === 'get_lead_vip_access') {
            $controller = new \App\Controllers\IntegrationController(
                $app->repositories->config,
                $app->repositories->person,
                $app->repositories->serviceGovernance
            );
            $controller->getLeadVipAccess();
            exit;
        }

        if ($action === 'reconcile_app_lead') {
            $controller = new \App\Controllers\IntegrationController(
                $app->repositories->config,
                $app->repositories->person,
                $app->repositories->serviceGovernance
            );
            $controller->reconcileAppLead();
            exit;
        }
        
        if ($action === 'batch_update_virtual_stages') {
            // Was reachable pre-auth (security hole). Require authentication only, so
            // no existing role loses access — every logged-in role could call it before.
            if (!$app->services->auth->isAuthenticated()) {
                echo json_encode(['status' => 'error', 'message' => 'لطفاً ابتدا وارد شوید']);
                exit;
            }
            // Batch update virtual stages
            $pdo = $app->db->getPdo();
            $stmt = $pdo->query("SELECT DISTINCT contact_didar_id FROM deals WHERE contact_didar_id IS NOT NULL AND contact_didar_id != ''");
            $contactIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
            
            $total = count($contactIds);
            $processed = 0;
            
            foreach ($contactIds as $contactId) {
                try {
                    $app->services->virtualStage->update($contactId);
                    $processed++;
                } catch (Exception $e) {
                    \App\Utils\Logger::logError("Failed to update virtual stage", $e, ['contact_id' => $contactId]);
                }
            }
            
            echo json_encode([
                'status' => 'success',
                'message' => "{$processed} از {$total} مراحل مجازی به‌روزرسانی شد"
            ]);
            exit;
        }

        // Generate Deal Title
        if ($action === 'generate_deal_title') {
            if (!$app->services->auth->isAuthenticated()) {
                echo json_encode(['status' => 'error', 'message' => 'لطفاً ابتدا وارد شوید']);
                exit;
            }
            $contactId = \App\Utils\Sanitizer::sanitize($_POST['contact_id'] ?? '');
            if (empty($contactId)) {
                echo json_encode(['status' => 'error', 'message' => 'شناسه شخص الزامی است']);
                exit;
            }

            try {
                // Prefer strict Didar lookup to avoid local numeric ID collisions
                $person = $app->repositories->person->findByDidarId($contactId);
                if (!$person) {
                    $person = $app->repositories->person->findByIdOrDidarId($contactId);
                }

                if (!$person) {
                    throw new Exception('شخص یافت نشد');
                }

                // Use the standardized Didar contact ID (GUID or real Didar numeric ID)
                $title = $app->services->deal->generateDealTitle($person->didar_contact_id);
                echo json_encode(['status' => 'success', 'title' => $title]);
            } catch (Exception $e) {
                echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
            }
            exit;
        }

        // Get allowed services
        if ($action === 'get_allowed_services') {
            if (!$app->services->auth->isAuthenticated()) {
                echo json_encode(['status' => 'error', 'message' => 'لطفاً ابتدا وارد شوید']);
                exit;
            }
            try {
                $services = $app->services->deal->getAllowedServices();
                echo json_encode(['status' => 'success', 'services' => $services]);
            } catch (Exception $e) {
                echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
            }
            exit;
        }

        if ($action === 'get_commission_matrix_data' || $action === 'get_commission_setup_data') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->getSetupData();
            exit;
        }

        if ($action === 'save_commission_rule' || $action === 'store_commission_rule') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->storeRule();
            exit;
        }

        if ($action === 'get_commission_rules') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->getRules();
            exit;
        }

        if ($action === 'assign_commission_rules') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->assignRules();
            exit;
        }

        if ($action === 'toggle_commission_assignment') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->toggleAssignment();
            exit;
        }

        if ($action === 'get_deal_commissions') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->getDealCommissions();
            exit;
        }

        if ($action === 'update_deal_commission_status') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->updateDealCommissionStatus();
            exit;
        }

        if ($action === 'delete_deal_commission') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->deleteDealCommission();
            exit;
        }

        if ($action === 'bulk_delete_commission_rules') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->bulkDeleteRules();
            exit;
        }

        if ($action === 'delete_commission_rule') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->deleteRule();
            exit;
        }

        if ($action === 'bulk_delete_deal_commissions') {
            $controller = new \App\Controllers\CommissionController(
                $app->services->commission,
                $app->services->auth,
                $app->repositories->user
            );
            $controller->bulkDeleteDealCommissions();
            exit;
        }

        // Auth endpoints (public)
        if ($action === 'login') {
            $controller = new \App\Controllers\AuthController($app->services->auth);
            $controller->login();
            exit;
        }
        
        if ($action === 'logout') {
            $controller = new \App\Controllers\AuthController($app->services->auth);
            $controller->logout();
            exit;
        }

        if ($action === 'log_client_event') {
            if ($app->services->auth->isAuthenticated()) {
                $logAction = $_POST['action'] ?? 'Client Event';
                $entityType = $_POST['entity_type'] ?? 'client_ui';
                $entityId = $_POST['entity_id'] ?? null;
                $details = $_POST['details'] ?? null;
                $relatedPersonId = $_POST['related_person_id'] ?? null;

                if (is_string($details)) {
                    $decoded = json_decode($details, true);
                    if (json_last_error() === JSON_ERROR_NONE) {
                        $details = $decoded;
                    }
                }

                $app->services->audit->log($logAction, $entityType, $entityId, $details, $relatedPersonId);
            }

            echo json_encode(['status' => 'success']);
            exit;
        }

        // Protected endpoints require authentication (after handling public/auth endpoints)
        if (!$app->services->auth->isAuthenticated()) {
            \App\Utils\Logger::logWarning('Auth check failed - not authenticated', [
                'session_id' => session_id(),
                'session_keys' => array_keys($_SESSION ?? []),
                'action' => $action
            ]);
            echo json_encode(['status' => 'error', 'message' => 'لطفاً ابتدا وارد شوید']);
            exit;
        }

        $rbacActionCapabilities = [
            'get_dashboard_stats' => 'dashboard.view',
            'get_lookup_groups' => 'lookups.view',
            'get_lookup_items' => 'lookups.view',
            'save_lookup_group' => 'lookups.edit',
            'save_lookup_item' => 'lookups.edit',
            'delete_lookup_group' => 'lookups.delete',
            'delete_lookup_item' => 'lookups.delete',
            'get_users_list' => 'users.view',
            'get_user' => 'users.view',
            'get_user_hierarchy' => 'users.view',
            'save_user' => 'users.edit',
            'save_user_hierarchy' => 'users.edit',
            'override_payment_owner' => 'payments.owner_override',
            'delete_user' => 'users.delete',
            'update_user_role' => 'users.roles.edit',
            'change_password' => 'users.passwords.change',
            'transfer_user_data' => 'users.transfer_data',
            'get_user_transfer_report' => 'users.transfer_data',
            'sync_didar_users' => 'users.sync_didar',
            'get_didar_users' => 'users.scope_options.view',
            'sync' => 'sync.run',
            'preview_migration' => 'migration.preview',
            'run_migration' => 'migration.run',
            'get_maintenance_dashboard' => 'maintenance.view',
            'list_db_backups' => 'maintenance.view',
            'create_db_backup' => 'maintenance.backup',
            'restore_db_backup' => 'maintenance.restore',
            'preview_payment_records_backfill' => 'maintenance.backfill.preview',
            'run_payment_records_backfill' => 'maintenance.backfill.run',
            'verify_payment_records_backfill' => 'maintenance.backfill.verify',
            'preview_activity_type_repair' => 'activity_repair.preview',
            'run_activity_type_repair' => 'activity_repair.run',
            'get_audit_logs' => 'audit_logs.view',
            'recover_deleted_record' => 'audit_logs.recover',
            'save_activity' => 'activities.create',
            'get_activity_details' => 'activities.view',
            'get_deal_activities' => 'activities.view',
            'get_contact_activities_local' => 'activities.view',
            'has_deal_activity' => 'activities.view',
            'get_activity_types' => 'activities.types.view',
            'update_activity' => 'activities.edit',
            'delete_activity' => 'activities.delete',
            'save_satisfaction' => 'satisfaction.create',
            'get_satisfactions' => 'satisfaction.view',
            'create_support' => 'support.create',
            'get_support_logs' => 'support.view',
            'get_support' => 'support.view',
            'update_support' => 'support.edit',
            'delete_support' => 'support.delete',
            'create_access_request' => 'customer_access.create',
            'get_access_requests' => 'customer_access.view',
            'get_access_request_inbox' => 'customer_access.resolve',
            'set_access_request_status' => 'customer_access.resolve',
            'get_notifications' => 'notifications.view',
            'get_notification_count' => 'notifications.view',
            'notification_count' => 'notifications.view',
            'mark_notification_read' => 'notifications.manage',
            'mark_all_notifications_read' => 'notifications.manage',
            'delete_notification' => 'notifications.manage',
            'check_reminders' => 'reminders.view',
            'get_reminders_list' => 'reminders.view',
            'resend_reminder' => 'reminders.manage',
            'mark_reminder_done' => 'reminders.manage',
            'snooze_reminder' => 'reminders.manage',
            'get_didar_write_settings' => 'settings.didar_write.manage',
            'save_didar_write_settings' => 'settings.didar_write.manage',
            'get_auto_migration_settings' => 'settings.auto_migration.manage',
            'save_auto_migration_settings' => 'settings.auto_migration.manage',
            'get_external_api_settings' => 'settings.external_api.manage',
            'save_external_api_settings' => 'settings.external_api.manage',
            'generate_external_api_token' => 'settings.external_api.manage',
            'revoke_external_api_token' => 'settings.external_api.manage',
            'set_master_password' => 'settings.master_password.manage',
            'get_field_configurations' => 'field_config.view',
            'get_field_configuration' => 'field_config.view',
            'get_field_configurations_by_entity' => 'field_config.view',
            'get_editable_fields' => 'field_config.view',
            'save_field_configuration' => 'field_config.edit',
            'delete_field_configuration' => 'field_config.delete',
            'update_field_edit_roles' => 'field_config.edit',
            'get_products' => 'products.view',
            'get_kpi_products' => 'products.view',
            'save_product' => 'products.edit',
            'delete_product' => 'products.delete',
            'save_service_product_links' => 'products.service_links.manage',
            'operation_manager_preview' => 'operation_manager.preview',
            'operation_manager_export' => 'operation_manager.preview',
            'operation_manager_execute' => 'operation_manager.execute',
            'operation_rules_list' => 'operation_manager.rules.view',
            'operation_rules_get' => 'operation_manager.rules.view',
            'operation_rules_save' => 'operation_manager.rules.manage',
            'operation_rules_delete' => 'operation_manager.rules.manage',
            'operation_rules_run' => 'operation_manager.automation.run',
            'operation_rules_run_due' => 'operation_manager.automation.run',
            'operation_runs_list' => 'operation_manager.view',
            'operation_runs_get' => 'operation_manager.view',
            'crm_lead_pool_list' => 'lead_pools.view',
            'lead_owner_history' => 'lead_owner_history.view',
        ];
        if (in_array($action, ['save_lookup_group', 'save_lookup_item'], true)) {
            $rbacActionCapabilities[$action] = (int)($_POST['id'] ?? 0) > 0 ? 'lookups.edit' : 'lookups.create';
        }
        if ($action === 'save_field_configuration') {
            $fieldName = trim((string)($_POST['field_name'] ?? ''));
            $rbacActionCapabilities[$action] = $fieldName !== '' ? 'field_config.edit' : 'field_config.create';
        }
        if ($action === 'save_product') {
            $rbacActionCapabilities[$action] = (int)($_POST['id'] ?? 0) > 0 ? 'products.edit' : 'products.create';
        }
        $requiresRbacCapability = isset($rbacActionCapabilities[$action]);
        if ($action === 'change_password') {
            $targetUserId = (int)($_POST['user_id'] ?? $_REQUEST['user_id'] ?? 0);
            $currentUserId = (int)($_SESSION['user_id'] ?? 0);
            $requiresRbacCapability = ($targetUserId !== $currentUserId);
        }

        if ($requiresRbacCapability && isset($app->services->rbac) && !$app->services->rbac->can($rbacActionCapabilities[$action])) {
            \App\Utils\Logger::logWarning('RBAC action denied', [
                'action' => $action,
                'capability' => $rbacActionCapabilities[$action],
                'user_id' => $_SESSION['user_id'] ?? null,
                'didar_id' => $_SESSION['didar_id'] ?? null,
                'role' => $_SESSION['role'] ?? null,
            ]);
            echo json_encode(['status' => 'error', 'message' => 'دسترسی محدود است']);
            exit;
        }

        $operationActions = [
            'operation_manager_preview' => 'preview',
            'operation_manager_export' => 'exportLeads',
            'operation_manager_execute' => 'execute',
            'operation_rules_list' => 'listRules',
            'operation_rules_get' => 'getRule',
            'operation_rules_save' => 'saveRule',
            'operation_rules_delete' => 'deleteRule',
            'operation_rules_run' => 'runRule',
            'operation_rules_run_due' => 'runDueRules',
            'operation_runs_list' => 'listRuns',
            'operation_runs_get' => 'getRun',
            'crm_lead_pool_list' => 'listPools',
            'lead_owner_history' => 'ownerHistory',
        ];
        if (isset($operationActions[$action])) {
            $controller = new \App\Controllers\OperationManagerController(
                $app->services->operationManager,
                $app->repositories->operation,
                $app->repositories->operationRule
            );
            $method = $operationActions[$action];
            $controller->{$method}();
            exit;
        }

        // Lookups (dynamic dropdowns)
        if ($action === 'get_lookups') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->getLookups();
            exit;
        }
        if ($action === 'get_lookup_groups') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->getGroups();
            exit;
        }
        if ($action === 'get_lookup_items') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->getItems();
            exit;
        }
        if ($action === 'save_lookup_group') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->saveGroup();
            exit;
        }
        if ($action === 'save_lookup_item') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->saveItem();
            exit;
        }
        if ($action === 'delete_lookup_group') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->deleteGroup();
            exit;
        }
        if ($action === 'delete_lookup_item') {
            $controller = new \App\Controllers\LookupController(
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->deleteItem();
            exit;
        }

        // Dashboard
        if ($action === 'get_dashboard_stats') {
            $controller = new \App\Controllers\DashboardController(
                $app->repositories->person,
                $app->repositories->deal,
                $app->repositories->activity,
                $app->repositories->lookup,
                $app->services->auth
            );
            $controller->getStats();
            exit;
        }

        // Users List for KPI filters
        if ($action === 'get_users_list') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->getList();
            exit;
        }

        // KPI Dashboard (admin only)
        if ($action === 'get_kpi') {
	            $controller = new \App\Controllers\KpiController(
	                $app->services->kpi,
	                $app->services->auth,
                    $app->services->commission
	            );
	            $controller->getKPI();
	            exit;
	        }
        if ($action === 'get_kpi_section') {
            $controller = new \App\Controllers\KpiController(
                $app->services->kpi,
                $app->services->auth,
                $app->services->commission
            );
            $controller->getKPISection();
            exit;
        }

        if ($action === 'get_commission_kpis') {
            $controller = new \App\Controllers\KpiController(
                $app->services->kpi,
                $app->services->auth,
                $app->services->commission
            );
            $controller->getCommissionKpis();
            exit;
        }

	        // Set KPI Target (admin only)
	        if ($action === 'set_kpi_target') {
	            $controller = new \App\Controllers\KpiController(
	                $app->services->kpi,
	                $app->services->auth,
                    $app->services->commission
	            );
	            $controller->setKpiTarget();
	            exit;
	        }

	        // Get KPI Targets (admin only)
	        if ($action === 'get_kpi_targets') {
	            $controller = new \App\Controllers\KpiController(
	                $app->services->kpi,
	                $app->services->auth,
                    $app->services->commission
	            );
	            $controller->getKpiTargets();
	            exit;
	        }

	        // Get KPI Deal Details (admin only)
	        if ($action === 'get_kpi_deals') {
	            $controller = new \App\Controllers\KpiController(
	                $app->services->kpi,
	                $app->services->auth,
                    $app->services->commission
	            );
	            $controller->getKpiDealDetails();
	            exit;
	        }

	        // KPI Drill-down (admin/agent with access rules)
	        if ($action === 'get_kpi_drilldown') {
	            $controller = new \App\Controllers\KpiController(
	                $app->services->kpi,
	                $app->services->auth,
                    $app->services->commission
	            );
	            $controller->getKpiDrilldown();
	            exit;
	        }

        // Performance Dashboard (admin/agent)
        if ($action === 'get_performance_dashboard') {
            $controller = new \App\Controllers\KpiController(
                $app->services->kpi,
                $app->services->auth,
                $app->services->commission
            );
            $controller->getPerformanceDashboard();
            exit;
        }
        if ($action === 'get_performance_dashboard_section') {
            $controller = new \App\Controllers\KpiController(
                $app->services->kpi,
                $app->services->auth,
                $app->services->commission
            );
            $controller->getPerformanceDashboardSection();
            exit;
        }

        if ($action === 'aggregate_commission_payout_cycles') {
            $controller = new \App\Controllers\PayrollController(
                $app->services->payrollIntegration,
                $app->services->auth
            );
            $controller->aggregateMonthlyPayouts();
            exit;
        }
        if ($action === 'get_commission_payout_queue') {
            $controller = new \App\Controllers\PayrollController(
                $app->services->payrollIntegration,
                $app->services->auth
            );
            $controller->getPayoutQueue();
            exit;
        }
        if ($action === 'decide_commission_payout') {
            $controller = new \App\Controllers\PayrollController(
                $app->services->payrollIntegration,
                $app->services->auth
            );
            $controller->decidePayout();
            exit;
        }

	        // Exports (admin only)
	        if ($action === 'export_catalog') {
	            $controller = new \App\Controllers\ExportController(
	                $app->services->export,
	                $app->services->auth,
                    $app->services->rbac
	            );
	            $controller->catalog();
	            exit;
	        }

        if ($action === 'export_run') {
	            $controller = new \App\Controllers\ExportController(
	                $app->services->export,
	                $app->services->auth,
                    $app->services->rbac
	            );
	            $controller->run();
	            exit;
	        }

        if ($action === 'bulk_phone_lookup') {
            $controller = new \App\Controllers\ImportController(
                $app->services->auth,
                $app->services->lead,
                $app->repositories->person,
                $app->repositories->user
            );
            $controller->bulkPhoneLookup();
            exit;
        }

        if ($action === 'import_leads_preview') {
            $controller = new \App\Controllers\ImportController(
                $app->services->auth,
                $app->services->lead,
                $app->repositories->person,
                $app->repositories->user
            );
            $controller->importLeadsPreview();
            exit;
        }

        if ($action === 'import_leads_execute') {
            $controller = new \App\Controllers\ImportController(
                $app->services->auth,
                $app->services->lead,
                $app->repositories->person,
                $app->repositories->user
            );
            $controller->importLeadsExecute();
            exit;
        }

        if ($action === 'download_leads_import_template') {
            $controller = new \App\Controllers\ImportController(
                $app->services->auth,
                $app->services->lead,
                $app->repositories->person,
                $app->repositories->user
            );
            $controller->downloadLeadsImportTemplate();
            exit;
        }

        if ($action === 'preview_activity_type_repair') {
            $controller = new \App\Controllers\ActivityRepairController(
                $app->services->auth,
                new \App\Services\ActivityTypeRepairService($app->db)
            );
            $controller->preview();
            exit;
        }

        if ($action === 'run_activity_type_repair') {
            $controller = new \App\Controllers\ActivityRepairController(
                $app->services->auth,
                new \App\Services\ActivityTypeRepairService($app->db)
            );
            $controller->run();
            exit;
        }

            if ($action === 'rbac_catalog') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->getCatalog();
                exit;
            }

            if ($action === 'rbac_role_permissions') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->getRolePermissions();
                exit;
            }

            if ($action === 'rbac_current_permissions') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->getCurrentPermissions();
                exit;
            }

            if ($action === 'rbac_user_permissions') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->getUserPermissions();
                exit;
            }

            if ($action === 'rbac_save_role') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->saveRole();
                exit;
            }

            if ($action === 'rbac_clone_role') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->cloneRole();
                exit;
            }

            if ($action === 'rbac_delete_role') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->deleteRole();
                exit;
            }

            if ($action === 'rbac_save_role_capabilities') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->saveRoleCapabilities();
                exit;
            }

            if ($action === 'rbac_save_role_scopes') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->saveRoleScopes();
                exit;
            }

            if ($action === 'rbac_save_user_capabilities') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->saveUserCapabilities();
                exit;
            }

            if ($action === 'rbac_save_user_scopes') {
                $controller = new \App\Controllers\RbacController(
                    $app->services->rbac,
                    $app->services->auth
                );
                $controller->saveUserScopes();
                exit;
            }

	                if ($action === 'get_audit_logs') {
	                    $controller = new \App\Controllers\AuditLogController(
	                        $app->repositories->auditLog,
	                        $app->services->auth,
                            $app->db
	                    );
	                    $controller->list();
	                    exit;
	                }

                    if ($action === 'recover_deleted_record') {
                        $controller = new \App\Controllers\AuditLogController(
                            $app->repositories->auditLog,
                            $app->services->auth,
                            $app->db
                        );
                        $controller->recoverDeletedRecord();
                        exit;
                    }
	        
                if ($action === 'log_client_event') {
                    if (!$app->services->auth->isAuthenticated()) {
                        exit;
                    }
                    $logAction = $_POST['action'] ?? 'Client Event';
                    $entityType = $_POST['entity_type'] ?? 'client_ui';
                    $entityId = $_POST['entity_id'] ?? null;
                    $details = $_POST['details'] ?? null;
                    $relatedPersonId = $_POST['related_person_id'] ?? null;
                    if (is_string($details)) {
                        $decoded = json_decode($details, true);
                        if (json_last_error() === JSON_ERROR_NONE) {
                            $details = $decoded;
                        }
                    }
                    $logAction = trim((string)$logAction);
                    $entityType = trim((string)$entityType);
                    if (in_array(strtolower($logAction), ['delete', 'recover', 'owner_change'], true)) {
                        $logAction = 'client:' . $logAction;
                    }
                    if (in_array(strtolower($entityType), ['person', 'deal', 'activity', 'payment'], true)) {
                        $entityType = 'client_' . $entityType;
                    }
                    $logAction = mb_substr($logAction, 0, 100);
                    $entityType = mb_substr($entityType, 0, 50);
                    $app->services->audit->log($logAction, $entityType, $entityId, $details, $relatedPersonId);
                    echo json_encode(['status' => 'success']);
                    exit;
                }
	                    	        // Leads
	                    	        if ($action === 'get_leads') {
	                    		        try {
	                    		            $controller = new \App\Controllers\LeadController(
	                    		                $app->services->lead,
	                    		                $app->services->virtualStage,
	                    		                $app->repositories->person,
	                    		                $app->repositories->activity,
	                    		                $app->repositories->deal,
	                    		                $app->services->auth,
	                    		                $app->services->audit
	                    		            );
	                    		            $controller->getLeads();
	                    		        } catch (\Exception $e) {
	                    	                \App\Utils\Logger::logError("API Error in get_leads", $e);
	                    	                echo json_encode(['status' => 'error', 'message' => 'خطا در بارگذاری لیدها']);
	                    	            }
	                    	            exit;
	                    	        }
	                    
	                    		        if ($action === 'lookup_mobile') {		            $controller = new \App\Controllers\LeadController(
		                $app->services->lead,
		                $app->services->virtualStage,
		                $app->repositories->person,
		                $app->repositories->activity,
		                $app->repositories->deal,
		                $app->services->auth,
		                $app->services->audit
		            );
		            $controller->lookupMobile();
		            exit;
		        }

	        if ($action === 'get_lead_didar_data') {
	            $controller = new \App\Controllers\DidarController(
	                $app->services->didarApi,
	                $app->repositories->person
	            );
            $controller->getLeadData();
            exit;
        }
        
	        if ($action === 'get_person_profile') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->getProfile();
	            exit;
	        }
        
	        if ($action === 'create_lead') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->create();
	            exit;
	        }
        
	        if ($action === 'update_lead') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->update();
	            exit;
	        }

	        if ($action === 'delete_lead') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->delete();
	            exit;
	        }

	        if ($action === 'transfer_owner') {
	            try {
	                $controller = new \App\Controllers\LeadController(
	                    $app->services->lead,
	                    $app->services->virtualStage,
	                    $app->repositories->person,
	                    $app->repositories->activity,
	                    $app->repositories->deal,
	                    $app->services->auth,
	                    $app->services->audit
	                );
	                $controller->transferOwner();
	            } catch (\Exception $e) {
                \App\Utils\Logger::logError("API Error in transfer_owner", $e, [
                    'contact_id' => $_POST['contact_id'] ?? null,
                    'new_owner_id' => $_POST['new_owner_id'] ?? null,
                    'user' => $_SESSION['didar_id'] ?? null
                ]);
                echo json_encode(['status' => 'error', 'message' => 'خطا در انتقال مسئول لید: ' . $e->getMessage()]);
            }
            exit;
        }

	        if ($action === 'get_referrals') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->getReferrals();
	            exit;
	        }

	        if ($action === 'backfill_lead_customer_products_from_requested_services') {
	            $controller = new \App\Controllers\LeadController(
	                $app->services->lead,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->activity,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit
	            );
	            $controller->backfillCustomerProductsFromRequestedServices();
	            exit;
	        }
        
        // Deals
	        if ($action === 'get_deals') {
	                   		            $controller = new \App\Controllers\DealController(
	                   		                $app->services->deal,
	                   		                $app->services->virtualStage,
	                   		                $app->repositories->person,
	                   		                $app->repositories->deal,
	                   		                $app->services->auth,
	                   		                $app->services->audit,
                    $app->db,
                    $app->services->commission
	                   		            );
	            $controller->getDeals();
	            exit;
	        }

	        if ($action === 'get_legacy_deals') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->getLegacyDeals();
	            exit;
	        }
        
	        if ($action === 'save_deal') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->save();
	            exit;
	        }

	        if ($action === 'upload_payment_file') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->uploadPaymentFile();
	            exit;
	        }

	        // Stream a stored payment receipt/cheque image (docroot-independent, auth-gated,
	        // correct Content-Type, optional download). Replaces the fragile static /public/ URL.
	        if ($action === 'payment_file') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->servePaymentFile();
	            exit;
	        }

	        // C9: financial cheque workflow
	        if ($action === 'get_cheques' || $action === 'set_cheque_status' || $action === 'set_cheque_collection') {
	            $controller = new \App\Controllers\ChequeController(
	                $app->repositories->chequeReview,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->db
	            );
	            if ($action === 'get_cheques') { $controller->list(); }
	            elseif ($action === 'set_cheque_status') { $controller->setStatus(); }
	            else { $controller->setCollection(); }
	            exit;
	        }

	        if (
	            $action === 'get_financial_payments'
	            || $action === 'mark_payment_sepidar'
	            || $action === 'override_payment_owner'
	            || $action === 'get_finance_cheque_inbox'
	            || $action === 'finance_approve_cheque'
	            || $action === 'finance_reject_cheque'
	        ) {
	            $controller = new \App\Controllers\PaymentController(
	                $app->repositories->paymentReview,
	                $app->services->auth,
	                $app->db,
	                $app->repositories->dealPayment,
	                $app->repositories->financeApproval,
	                $app->services->commission
	            );
	            if ($action === 'get_financial_payments') { $controller->list(); }
	            elseif ($action === 'mark_payment_sepidar') { $controller->markSepidar(); }
	            elseif ($action === 'override_payment_owner') { $controller->overridePaymentOwner(); }
	            elseif ($action === 'get_finance_cheque_inbox') { $controller->financeChequeInbox(); }
	            elseif ($action === 'finance_approve_cheque') { $controller->approveFinanceCheque(); }
	            else { $controller->rejectFinanceCheque(); }
	            exit;
	        }
        
	        if ($action === 'set_deal_status') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->setStatus();
	            exit;
	        }

	        if ($action === 'set_deal_pipeline_stage') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->setPipelineStage();
	            exit;
	        }

	        if ($action === 'set_course_status') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->setCourseStatus();
	            exit;
	        }
        
	        if ($action === 'delete_deal') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->delete();
	            exit;
	        }

	        if ($action === 'deal/reactivate') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->reactivate();
	            exit;
	        }

	        if ($action === 'deal/move_to_parked') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->moveToParked();
	            exit;
	        }

	        if ($action === 'deal/move_out_of_parked') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->moveOutOfParked();
	            exit;
	        }

	        if ($action === 'deal/move_stage_to_parked') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->moveStageToParked();
	            exit;
	        }

	        if ($action === 'deal/move_stage_out_of_parked') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->moveStageOutOfParked();
	            exit;
	        }

	        if ($action === 'deal/unpark_all') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->unparkAll();
	            exit;
	        }

	        if ($action === 'deal/force_success_exit_kariz') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->forceSuccessAndExitKariz();
	            exit;
	        }

	        if ($action === 'deal/reconcile_won_kariz_preview') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->previewWonKarizReconcile();
	            exit;
	        }

	        if ($action === 'deal/reconcile_won_kariz_run') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db,
	                $app->services->commission
	            );
	            $controller->runWonKarizReconcile();
	            exit;
	        }

	        if ($action === 'deal/reconcile_lost_kariz_preview') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->previewLostKarizReconcile();
	            exit;
	        }

	        if ($action === 'deal/reconcile_lost_kariz_run') {
	            $controller = new \App\Controllers\DealController(
	                $app->services->deal,
	                $app->services->virtualStage,
	                $app->repositories->person,
	                $app->repositories->deal,
	                $app->services->auth,
	                $app->services->audit,
	                $app->db
	            );
	            $controller->runLostKarizReconcile();
	            exit;
	        }
        
        // Activities
        if ($action === 'save_activity') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->save();
            exit;
        }
        
        if ($action === 'get_activity_details') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->getActivityDetails();
            exit;
        }
        
        if ($action === 'update_activity') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->update();
            exit;
        }
        
        if ($action === 'delete_activity') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->delete();
            exit;
        }

        if ($action === 'get_deal_activities') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->getDealActivities();
            exit;
        }

        if ($action === 'get_contact_activities_local') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->getContactActivitiesLocal();
            exit;
        }

        if ($action === 'has_deal_activity') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->hasDealActivity();
            exit;
        }
        
        // Sync
        if ($action === 'sync') {
            $controller = new \App\Controllers\SyncController(
                $app->services->sync,
                $app->services->auth
            );
            $controller->sync();
            exit;
        }

        if ($action === 'preview_migration') {
            $controller = new \App\Controllers\MigrationController(
                $app->services->auth,
                $app->db
            );
            $controller->preview();
            exit;
        }

        if ($action === 'run_migration') {
            $controller = new \App\Controllers\MigrationController(
                $app->services->auth,
                $app->db
            );
            $controller->run();
            exit;
        }

        if ($action === 'get_maintenance_dashboard') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->dashboard();
            exit;
        }

        if ($action === 'list_db_backups') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->listBackups();
            exit;
        }

        if ($action === 'create_db_backup') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->createBackup();
            exit;
        }

        if ($action === 'restore_db_backup') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->restoreBackup();
            exit;
        }

        if ($action === 'preview_payment_records_backfill') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->previewPaymentRecordsBackfill();
            exit;
        }

        if ($action === 'run_payment_records_backfill') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->runPaymentRecordsBackfill();
            exit;
        }

        if ($action === 'verify_payment_records_backfill') {
            $controller = new \App\Controllers\MaintenanceController(
                $app->services->auth,
                $app->services->databaseMaintenance,
                $app
            );
            $controller->verifyPaymentRecordsBackfill();
            exit;
        }
        
        // Users
        if ($action === 'get_users_list') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->getList();
            exit;
        }

        if ($action === 'get_user') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->getOne();
            exit;
        }

        if ($action === 'get_user_hierarchy') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->getHierarchyAssignments();
            exit;
        }
        
        if ($action === 'save_user') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->save();
            exit;
        }

        if ($action === 'save_user_hierarchy') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config,
                $app->services->userHierarchy
            );
            $controller->saveHierarchyAssignment();
            exit;
        }

        if ($action === 'transfer_user_data') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config
            );
            $controller->transferAllOwnership();
            exit;
        }

        if ($action === 'get_user_transfer_report') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config
            );
            $controller->getTransferReport();
            exit;
        }

        if ($action === 'delete_user') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config
            );
            $controller->deleteUser();
            exit;
        }

        if ($action === 'update_user_role') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                null,
                $app->db,
                $app->repositories->config
            );
            $controller->updateRole();
            exit;
        }
        
        if ($action === 'change_password') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth
            );
            $controller->changePassword();
            exit;
        }

        if ($action === 'set_master_password') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->setMasterPassword();
            exit;
        }

        if ($action === 'sync_didar_users') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                $app->services->didarApi,
                $app->db
            );
            $controller->syncDidarUsers();
            exit;
        }
        
        if ($action === 'get_didar_users') {
            $controller = new \App\Controllers\UserController(
                $app->repositories->user,
                $app->services->auth,
                $app->services->didarApi,
                $app->db
            );
            $controller->getDidarUsers();
            exit;
        }
        
        // Get Deal
        if ($action === 'get_deal') {
            $controller = new \App\Controllers\DealController(
                $app->services->deal,
                $app->services->virtualStage,
                $app->repositories->person,
                $app->repositories->deal,
                $app->services->auth,
                $app->services->audit,
                $app->db,
                $app->services->commission
            );
            $controller->getDeal();
            exit;
        }
        
        // Satisfaction endpoints
        if ($action === 'save_satisfaction') {
            $controller = new \App\Controllers\SatisfactionController(
                $app->repositories->satisfaction,
                $app->repositories->person,
                $app->services->auth
            );
            $controller->save();
            exit;
        }
        
        if ($action === 'get_satisfactions') {
            $controller = new \App\Controllers\SatisfactionController(
                $app->repositories->satisfaction,
                $app->repositories->person,
                $app->services->auth
            );
            $controller->getSatisfactions();
            exit;
        }
        
        // Customer access requests (ticketing: sales expert -> support)
        if (in_array($action, ['create_access_request', 'get_access_requests', 'get_access_request_inbox', 'set_access_request_status'], true)) {
            $controller = new \App\Controllers\AccessRequestController(
                $app->repositories->accessRequest,
                $app->repositories->person
            );
            if ($action === 'create_access_request') { $controller->create(); }
            elseif ($action === 'get_access_requests') { $controller->getForContact(); }
            elseif ($action === 'get_access_request_inbox') { $controller->getInbox(); }
            else { $controller->setStatus(); }
            exit;
        }

        // Support endpoints (admin and CRM specialist only)
        if ($action === 'create_support') {
            $controller = new \App\Controllers\SupportController(
                $app->services->support,
                $app->services->auth
            );
            $controller->create();
            exit;
        }
        
        if ($action === 'get_support_logs') {
            $controller = new \App\Controllers\SupportController(
                $app->services->support,
                $app->services->auth
            );
            $controller->getByContactId();
            exit;
        }
        
        if ($action === 'update_support') {
            $controller = new \App\Controllers\SupportController(
                $app->services->support,
                $app->services->auth
            );
            $controller->update();
            exit;
        }
        
        if ($action === 'delete_support') {
            $controller = new \App\Controllers\SupportController(
                $app->services->support,
                $app->services->auth
            );
            $controller->delete();
            exit;
        }
        
        if ($action === 'get_support') {
            $controller = new \App\Controllers\SupportController(
                $app->services->support,
                $app->services->auth
            );
            $controller->getById();
            exit;
        }
        
        // Get Activity Types
        if ($action === 'get_activity_types') {
            $controller = new \App\Controllers\ActivityController(
                $app->services->activity,
                $app->services->virtualStage,
                $app->services->didarApi,
                $app->services->auth,
                $app->repositories->person,
                $app->services->audit
            );
            $controller->getActivityTypes();
            exit;
        }
        
        // Notification endpoints
        if ($action === 'get_notifications') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->getNotifications();
            exit;
        }
        
        if ($action === 'get_notification_count' || $action === 'notification_count') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->getUnreadCount();
            exit;
        }

        if ($action === 'get_didar_write_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->getDidarWriteSettings();
            exit;
        }

        if ($action === 'save_didar_write_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->saveDidarWriteSettings();
            exit;
        }

        if ($action === 'get_auto_migration_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->getAutoMigrationSettings();
            exit;
        }

        if ($action === 'save_auto_migration_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->saveAutoMigrationSettings();
            exit;
        }

        if ($action === 'get_external_api_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->getExternalApiSettings();
            exit;
        }

        if ($action === 'save_external_api_settings') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->saveExternalApiSettings();
            exit;
        }

        if ($action === 'generate_external_api_token') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->generateExternalApiToken();
            exit;
        }

        if ($action === 'revoke_external_api_token') {
            $controller = new \App\Controllers\SettingsController(
                $app->repositories->config,
                $app->services->auth
            );
            $controller->revokeExternalApiToken();
            exit;
        }

        if ($action === 'get_service_governance_settings') {
            $controller = new \App\Controllers\ServiceGovernanceController(
                $app->repositories->serviceGovernance,
                $app->repositories->user,
                $app->services->auth
            );
            $controller->getServiceGovernanceSettings();
            exit;
        }

        if ($action === 'save_service_governance_settings') {
            $controller = new \App\Controllers\ServiceGovernanceController(
                $app->repositories->serviceGovernance,
                $app->repositories->user,
                $app->services->auth
            );
            $controller->saveServiceGovernanceSettings();
            exit;
        }

        // Field Configuration (Admin only)
        if ($action === 'get_field_configurations') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->getAll();
            exit;
        }

        if ($action === 'get_field_configurations_public') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->getByEntityPublic();
            exit;
        }

        if ($action === 'get_field_configuration') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->getByFieldName();
            exit;
        }

        if ($action === 'get_field_configurations_by_entity') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->getByEntity();
            exit;
        }

        if ($action === 'get_editable_fields') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->getEditableFields();
            exit;
        }

        if ($action === 'save_field_configuration') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->save();
            exit;
        }

        if ($action === 'delete_field_configuration') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->delete();
            exit;
        }

        if ($action === 'update_field_edit_roles') {
            $controller = new \App\Controllers\FieldConfigController(
                $app->repositories->fieldConfig,
                $app->services->fieldPermission,
                $app->services->auth
            );
            $controller->updateEditRoles();
            exit;
        }

        // Products
        if ($action === 'get_products') {
            $controller = new \App\Controllers\ProductController(
                $app->repositories->product,
                $app->services->auth
            );
            $controller->getList();
            exit;
        }
        if ($action === 'get_kpi_products') {
            $controller = new \App\Controllers\ProductController(
                $app->repositories->product,
                $app->services->auth
            );
            $controller->getKpiList();
            exit;
        }
        if ($action === 'save_product') {
            $controller = new \App\Controllers\ProductController(
                $app->repositories->product,
                $app->services->auth
            );
            $controller->save();
            exit;
        }
        if ($action === 'delete_product') {
            $controller = new \App\Controllers\ProductController(
                $app->repositories->product,
                $app->services->auth
            );
            $controller->delete();
            exit;
        }
        if ($action === 'save_service_product_links') {
            $controller = new \App\Controllers\ProductController(
                $app->repositories->product,
                $app->services->auth
            );
            $controller->saveServiceLinks();
            exit;
        }
        
        if ($action === 'mark_notification_read') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->markAsRead();
            exit;
        }
        
        if ($action === 'mark_all_notifications_read') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->markAllAsRead();
            exit;
        }
        
        if ($action === 'delete_notification') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->delete();
            exit;
        }
        
        if ($action === 'check_reminders') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->checkReminders();
            exit;
        }
        
        if ($action === 'test_notification') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->test();
            exit;
        }

        if ($action === 'get_reminders_list') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->getRemindersList();
            exit;
        }

        if ($action === 'resend_reminder') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->resendReminder();
            exit;
        }

        if ($action === 'mark_reminder_done') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->markReminderDone();
            exit;
        }

        if ($action === 'snooze_reminder') {
            $controller = new \App\Controllers\NotificationController(
                $app->services->notification,
                $app->services->auth
            );
            $controller->snoozeReminder();
            exit;
        }
        
        // Additional endpoints that need more complex logic
        // For now, return a helpful message
        $complexEndpoints = [
            'save_satisfaction', 'get_satisfactions',
            'create_new_request_activity',
            'get_crm_settings', 'save_crm_settings',
            'search_didar', 'get_didar_person',
            'get_deal_details',
            'check_duplicate_phone'
        ];
        
        if (in_array($action, $complexEndpoints)) {
            echo json_encode([
                'status' => 'error',
                'message' => 'This endpoint requires additional migration. Please use the old index.php temporarily.',
                'endpoint' => $action
            ]);
            exit;
        }
        
        // Unknown endpoint - try to handle via old index.php as fallback
        if (file_exists(__DIR__ . '/../index.php')) {
            // For endpoints not yet migrated, try old index.php
            // This allows gradual migration
            $oldIndexPath = __DIR__ . '/../index.php';
            // We'll include it but need to set up globals
            global $pdo;
            $pdo = $app->db->getPdo();
            
            // Note: This is a temporary solution during migration
            // Eventually all endpoints should be in controllers
            \App\Utils\Logger::logWarning("Endpoint handled by old index.php", ['action' => $action]);
            
            // For now, return error message
            echo json_encode([
                'status' => 'error',
                'message' => 'Endpoint not yet fully migrated: ' . $action . '. Please check migration status.',
                'endpoint' => $action
            ]);
        } else {
            echo json_encode(['status' => 'error', 'message' => 'Endpoint not found: ' . $action]);
        }
        
    } catch (Exception $e) {
        \App\Utils\Logger::logError("API Error", $e, ['action' => $action]);
        echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
    }
    
    exit;
}

// For non-API requests, serve the new frontend using views/layouts/app.php
// Decide which page to show: setup, login, or dashboard based on DB and session

/**
 * Render a page inside the main application layout.
 *
 * @param string $viewPath Absolute path to the view file (content only).
 * @param array  $vars     Variables to extract for the view.
 */
function renderAppView(string $viewPath, array $vars = []): void
{
    extract($vars, EXTR_SKIP);

    ob_start();
    require $viewPath;
    $content = ob_get_clean();

    require __DIR__ . '/../views/layouts/app.php';
}

if ($mockMode) {
    $isSetup = true;
} else {
    $pdo = $app->db->getPdo();
    $stmt = $pdo->query("SELECT count(*) FROM users WHERE role='admin'");
    $isSetup = $stmt->fetchColumn() > 0;
    if (!$isSetup) {
        $totalUsers = $pdo->query("SELECT count(*) FROM users")->fetchColumn();
        $apiKey = $app->repositories->config->getValue('api_key');
        $isSetup = ($totalUsers > 0) || !empty($apiKey);
    }
}

if (!$isSetup) {
    // System not installed yet -> show setup wizard
    renderAppView(__DIR__ . '/../views/pages/setup.php');
    exit;
}

// System is installed, check authentication
if (!$app->services->auth->isAuthenticated()) {
    // Not logged in -> show login page
    renderAppView(__DIR__ . '/../views/pages/login.php');
    exit;
}

// Logged in -> show main dashboard
renderAppView(__DIR__ . '/../views/pages/dashboard.php');
