<?php

/**Third Party Modules Go Here **/

/**Third Party Modules Go Here **/
require_once('/usr/share/php/v2/RealTimeFetcher.php');
require_once('/usr/share/php/v2/api_conf.php');
require_once('/usr/share/php/v2/AstMan.php');
require_once('/usr/share/php/v2/AstMan2.php');
require_once('/usr/share/php/v2/WsApi.php');
require_once('/usr/share/php/v2/AriApi.php');

require_once('/usr/share/php/v2/ApiData.php');
require_once('/usr/share/php/v2/ApiController.php');

// OutDial System
require_once('/usr/share/php/v2/OutDialCampaignData.php');
require_once('/usr/share/php/v2/OutDialCampaignController.php');
require_once('/usr/share/php/v2/OutDialTargetData.php');
require_once('/usr/share/php/v2/OutDialTargetController.php');
require_once('/usr/share/php/v2/OutDialPoolData.php');
require_once('/usr/share/php/v2/OutDialPoolController.php');
require_once('/usr/share/php/v2/OutDialUsageData.php');
require_once('/usr/share/php/v2/OutDialUsageController.php');

require_once('/usr/share/php/v2/CustomerBalanceData.php');
require_once('/usr/share/php/v2/CustomerBalanceController.php');

require_once('/usr/share/php/v2/CustomerAnalysisData.php');
require_once('/usr/share/php/v2/CustomerAnalysisController.php');

require_once('/usr/share/php/v2/OutDialPricingData.php');
require_once('/usr/share/php/v2/OutDialPricingController.php');

require_once('/usr/share/php/v2/CustomersData.php');
require_once('/usr/share/php/v2/CustomersController.php');

require_once('/usr/share/php/v2/NumbersData.php');
require_once('/usr/share/php/v2/NumbersController.php');

require_once('/usr/share/php/v2/CustSiteData.php');
require_once('/usr/share/php/v2/CustSiteController.php');

require_once('/usr/share/php/v2/PkgSubActData.php');
require_once('/usr/share/php/v2/PkgSubActController.php');

require_once('/usr/share/php/v2/ServicesData.php');
require_once('/usr/share/php/v2/ServicesController.php');

require_once('/usr/share/php/v2/DevModelData.php');
require_once('/usr/share/php/v2/DevModelController.php');

require_once('/usr/share/php/v2/SvcPackageController.php');
require_once('/usr/share/php/v2/SvcPackageData.php');

require_once('/usr/share/php/v2/CustServiceData.php');
require_once('/usr/share/php/v2/CustServiceController.php');

require_once('/usr/share/php/v2/ServiceMapData.php');
require_once('/usr/share/php/v2/ServiceMapController.php');

require_once('/usr/share/php/v2/DeviceData.php');
require_once('/usr/share/php/v2/DeviceController.php');

require_once('/usr/share/php/v2/ExtDeviceData.php');
require_once('/usr/share/php/v2/ExtDeviceController.php');

require_once('/usr/share/php/v2/CustExtensionData.php');
require_once('/usr/share/php/v2/CustExtensionController.php');

require_once('/usr/share/php/v2/ActivityData.php');
require_once('/usr/share/php/v2/ActivityController.php');

require_once('/usr/share/php/v2/OnboardData.php');
require_once('/usr/share/php/v2/OnboardController.php');

require_once('/usr/share/php/v2/AudioData.php');
require_once('/usr/share/php/v2/AudioController.php');

require_once('/usr/share/php/v2/IvrData.php');
require_once('/usr/share/php/v2/IvrController.php');

require_once('/usr/share/php/v2/VoiceBcastData.php');
require_once('/usr/share/php/v2/VoiceBcastController.php');

require_once('/usr/share/php/v2/CallDistData.php');
require_once('/usr/share/php/v2/CallDistController.php');

require_once('/usr/share/php/v2/VoicemailData.php');
require_once('/usr/share/php/v2/VoicemailController.php');

require_once('/usr/share/php/v2/ConfBridgeData.php');
require_once('/usr/share/php/v2/ConfBridgeController.php');

require_once('/usr/share/php/v2/ConfMapData.php');
require_once('/usr/share/php/v2/ConfMapController.php');

require_once('/usr/share/php/v2/QueueData.php');
require_once('/usr/share/php/v2/QueueController.php');

require_once('/usr/share/php/v2/LangData.php');
require_once('/usr/share/php/v2/LangController.php');

require_once('/usr/share/php/v2/RequestData.php');
require_once('/usr/share/php/v2/RequestController.php');

require_once('/usr/share/php/v2/ReportData.php');
require_once('/usr/share/php/v2/ReportController.php');

require_once('/usr/share/php/v2/ContactsData.php');
require_once('/usr/share/php/v2/ContactsController.php');

require_once('/usr/share/php/v2/ResReportData.php');
require_once('/usr/share/php/v2/ResReportController.php');

require_once('/usr/share/php/v2/TagReportData.php');
require_once('/usr/share/php/v2/TagReportController.php');

require_once('/usr/share/php/v2/NewIvrData.php');
require_once('/usr/share/php/v2/NewIvrController.php');

require_once('/usr/share/php/v2/ResellerData.php');
require_once('/usr/share/php/v2/ResellerController.php');

require_once('/usr/share/php/v2/CallData.php');
require_once('/usr/share/php/v2/CallController.php');

require_once('/usr/share/php/v2/TicketData.php');
require_once('/usr/share/php/v2/TicketController.php');

require_once('/usr/share/php/v2/RealtimeReportData.php');
require_once('/usr/share/php/v2/RealtimeReportController.php');

require_once('/usr/share/php/v2/QueueMemberData.php');
require_once('/usr/share/php/v2/QueueMemberController.php');

require_once('/usr/share/php/v2/SurveyData.php');
require_once('/usr/share/php/v2/SurveyController.php');

require_once('/usr/share/php/v2/MohData.php');
require_once('/usr/share/php/v2/MohController.php');

require_once('/usr/share/php/v2/NewReportData.php');
require_once('/usr/share/php/v2/NewReportController.php');

require_once('/usr/share/php/v2/TelegramData.php');
require_once('/usr/share/php/v2/TelegramController.php');

require_once('/usr/share/php/v2/HistoricalReportData.php');
require_once('/usr/share/php/v2/HistoricalReportController.php');

require_once('/usr/share/php/v2/ClientData.php');
require_once('/usr/share/php/v2/ClientController.php');

require_once('/usr/share/php/v2/SchemaDefinitionData.php');
require_once('/usr/share/php/v2/SchemaDefinitionController.php');

require_once('/usr/share/php/v2/TelegramBotData.php');
require_once('/usr/share/php/v2/TelegramBotController.php');

require_once('/usr/share/php/v2/TelegramMenuData.php');
require_once('/usr/share/php/v2/TelegramMenuController.php');

require_once('/usr/share/php/v2/TelegramUserMapData.php');
require_once('/usr/share/php/v2/TelegramWebhookController.php');


require_once('/usr/share/php/v2/TelegramMessageData.php');
require_once('/usr/share/php/v2/TelegramMessageController.php');
require_once('/usr/share/php/v2/TelegramChatController.php');

require_once('/usr/share/php/v2/TestData.php');
require_once('/usr/share/php/v2/TestController.php');

require_once('/usr/share/php/v2/BlackListData.php');
require_once('/usr/share/php/v2/BlackListController.php');


require_once('/usr/share/php/v2/CallCenterReportData.php');
require_once('/usr/share/php/v2/CallCenterReportController.php');

require_once('/usr/share/php/v2/ExtendedReportData.php');
require_once('/usr/share/php/v2/ExtendedReportController.php');

require_once('/usr/share/php/v2/AdvancedReportData.php');
require_once('/usr/share/php/v2/AdvancedReportController.php');


// Billing System
require_once('/usr/share/php/v2/Models/HasabPackage.php');
require_once('/usr/share/php/v2/Models/CustomerPackageSubscription.php');
require_once('/usr/share/php/v2/Models/HasabUsageLog.php');
require_once('/usr/share/php/v2/Models/InvoiceHeader.php');
require_once('/usr/share/php/v2/Models/InvoiceItem.php');
require_once('/usr/share/php/v2/BillingController.php');

// Hasab API Integration
require_once('/usr/share/php/v2/HasabApiService.php');
require_once('/usr/share/php/v2/HasabApiController.php');

require_once('/usr/share/php/v2/ApiKeyData.php');
require_once('/usr/share/php/v2/ApiKeyController.php');

require_once('/usr/share/php/v2/DownloadQueueData.php');
require_once('/usr/share/php/v2/DownloadQueueController.php');
require_once('/usr/share/php/v2/AudioBatchProcessor.php');

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Expose-Headers: *");
header("Access-Control-Allow-Headers: *");

$authorized = false;
/*if (isset($_SERVER['HTTP_X_API_KEY'])) {
	if (in_array($_SERVER['HTTP_X_API_KEY'], $_valid_api_keys)) $authorized = true;
}*/


/*
$auth_res = check_auth();
//*** Faking login

if (!$auth_res['is_token_valid']) {
        header('HTTP/1.1 401 Unauthorized');
        exit();
}
$created_by = $auth_res['created_by'];
$scope_roles = $auth_res['roles'];
$auth_data = [
	'created_by' => $created_by,
	'scope_roles' => $scope_roles
];

//**** End faking
 */
$requestUri = $_SERVER['REQUEST_URI'];
$uriParts = parse_url($requestUri);

$path = isset($uriParts['path']) ? $uriParts['path'] : '';
$path = preg_replace('~^/api/v2/~', '', $path);
$parts = explode('/', trim($path, '/'));

$notFound = false;
if (isset($parts[0])) {
	$item = strtolower($parts[0]);
	if(is_numeric($parts[0])){
		$item = "contact";
	}
	$param1 = isset($parts[1])?$parts[1]:null;
	$param2 = isset($parts[2])?$parts[2]:null;
	$param3 = isset($parts[3])?$parts[3]:null;
	$param4 = isset($parts[4])?$parts[4]:null;
	//if (!in_array($item, array('cust', 'number'))) $notFound = true;
} else $notFound = true;

if ($notFound) {
	header("HTTP/1.1 404 Not Found ");
	exit();
}

$requestMethod = $_SERVER["REQUEST_METHOD"];
if ($requestMethod == 'OPTIONS') {
	header("Access-Control-Allow-Methods: GET, POST,PUT, PATCH, DELETE, OPTIONS");
	header("Access-Control-Allow-Headers: X-API-KEY, Authorization, authorization, Content-Type,Accept, Origin");
        exit(0);
}
$_qstr_sfx = "";
if ($requestMethod == 'GET') {
	if (isset($_GET['sortby'])) {
		$sort_field = $_GET['sortby'];
		if (preg_match('/^[a-z0-9\_]*$/',$sort_field)) {
			$order = "ASC";
			if (isset($_GET['order']) and strtoupper($_GET['order']) == 'DESC') {
				$order = "DESC";
			}
			$_qstr_sfx .= " ORDER BY $sort_field $order";
		}
	}
	if (isset($_GET['psize'])) {
		$psize = $_GET['psize'];
		if (preg_match('/^[1-9][0-9]*$/', $psize)) {
			$offset = 0;
			if (isset($_GET['pnum'])) {
				$pnum = $_GET['pnum'];
				if (preg_match('/^[1-9][0-9]*$/', $pnum)) {
					$offset = $psize * ($pnum-1);
				}
			}
			$_qstr_sfx .= " LIMIT $psize OFFSET $offset";
		}
	}
}
//*************************Check Auth Begin****************************
$unauth_resp = [						    //*
		'is_token_valid' => false,			    //*
		'created_by' => null,				    //*
		'roles' => false,				    //*
	];							    //*
$auth_res = check_auth($_valid_api_keys, $unauth_resp, $item);	    //*
if (!$auth_res['is_token_valid']) {				    //*
        header('HTTP/1.1 401 Unauthorized');			    //*
        exit();						  	    //*
}								    //*
$created_by = $auth_res['created_by'];				    //*
$scope_roles = $auth_res['roles'];				    //*
$auth_data = [							    //*
        'created_by' => $created_by,				    //*
        'scope_roles' => $scope_roles				    //*
];
if ($param1 >= 46 && $item != 'ticket' && $param1 && preg_match('/^\d+$/', $param1) && $created_by != 999999) {
    $expected_key = "C:$param1";
    if (!array_key_exists($expected_key, $scope_roles)) {
        header('HTTP/1.1 403 Forbidden');
        echo json_encode([
            'error' => 'Access to this customer is forbidden. repeated access will get your account suspended',
            'reason' => "Missing scope for $expected_key"
	]);
	file_put_contents("/var/www/pbx/log/bannable_accounts.log", date("Y-m-d H:i:s") . ": BAN ACC: $created_by tried to access $expected_key \n", FILE_APPEND);
	exit();
    }
}								    //*
//*************************End Check Auth******************************

switch ($item) {
case 'cust':
	$customersController = new CustomersController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$customersController->processRequest();
	break;

case 'number':
	$numbersController = new NumbersController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$numbersController->processRequest();
	break;

case 'cust_site':
	$custSiteController = new CustSiteController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$custSiteController->processRequest();
	break;

case 'pkg_sub_act':
	$pkgSubActController = new PkgSubActController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$pkgSubActController->processRequest();
	break;

case 'service':
	$servicesController = new ServicesController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$servicesController->processRequest();
	break;

case 'svc_pkg':
	$svcPackageController = new SvcPackageController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$svcPackageController->processRequest();
	break;

case 'dev_model':
	$devModelController = new DevModelController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$devModelController->processRequest();
	break;

case 'cust_service':
	$custServiceController = new CustServiceController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$custServiceController->processRequest();
	break;

case 'service_map':
	$serviceMapController = new ServiceMapController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$serviceMapController->processRequest();
	break;

case 'cust_ext':
	$custExtensionController = new CustExtensionController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$custExtensionController->processRequest();
	break;

case 'device':
	$deviceController = new DeviceController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$deviceController->processRequest();
	break;

case 'ext_device':
	$extDeviceController = new ExtDeviceController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$extDeviceController->processRequest();
	break;

case 'activity':
	$activityController = new ActivityController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$activityController->processRequest();
	break;

case 'onboard':
	$onboardController = new OnboardController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$onboardController->processRequest();
	break;

case 'audio':
	$audioController = new AudioController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$audioController->processRequest();
	break;

case 'ivr':
	$ivrController = new IvrController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$ivrController->processRequest();
	break;
case 'call_dist':
	$callDistController = new CallDistController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$callDistController->processRequest();
	break;
case 'vm':
	$voicemailController = new VoicemailController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$voicemailController->processRequest();
	break;
case 'vbcast':
	$voiceBcastController = new VoiceBcastController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$voiceBcastController->processRequest();
	break;

case 'conf':
	$confBridgeController = new ConfBridgeController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$confBridgeController->processRequest();
	break;

case 'confmap':
	$confMapController = new ConfMapController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$confMapController->processRequest();
	break;
case 'cust_queue':
	$queueController = new QueueController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$queueController->processRequest();
	break;
case 'cust_lang':
	$langController = new LangController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$langController->processRequest();
	break;
case 'cust_rep':
        $repController = new ReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $repController->processRequest();
	break;

case 'cust_req':
        $requestController = new RequestController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $requestController->processRequest();
	break;
case 'res_rep':
        $resReportController = new ResReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $resReportController->processRequest();
	break;
case 'contact':
        $contactsController = new ContactsController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $contactsController->processRequest();
	break;
case 'call':
        $callController = new CallController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $callController->processRequest();
        break;
case 'tag-report':
        $tagReportController = new TagReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tagReportController->processRequest();
	break;
case 'new-ivr':
        $newIvrController = new NewIvrController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $newIvrController->processRequest();
        break;

case 'reseller':
        $resellerController = new ResellerController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $resellerController->processRequest();
	break;
case 'ticket':
        $ticketController = new TicketController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $ticketController->processRequest();
	break;
case 'realtime':
        $rtController = new RealtimeReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $rtController->processRequest();
	break;
case 'member':
        $qmController = new QueueMemberController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $qmController->processRequest();
	break;
case 'survey':
        $surveyController = new SurveyController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $surveyController->processRequest();
	break;

case 'moh':
        $mohController = new MohController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $mohController->processRequest();
        break;
case 'new-report':
	$nrController = new NewReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $nrController->processRequest();
	break;

case 'telegram':
        $tgController = new TelegramController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tgController->processRequest();
        break;

case 'historical':
        $histController = new HistoricalReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $histController->processRequest();
        break;

case 'crm':
        $crmController = new ClientController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $crmController->processRequest();
        break;

case 'schema':
        $schemaController = new SchemaDefinitionController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $schemaController->processRequest();
	break;

case 'customer-analysis':
	$customerAnalysisController = new CustomerAnalysisController($dbh, $dbhr, $requestMethod,
		$param1, $param2, $param3, $param4, $created_by, $auth_data);
	$customerAnalysisController->processRequest();
	break;

/*
 * New Api definitions for Telegram Social integration
*/
case 'tg_bot':
        $tgBotController = new TelegramBotController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tgBotController->processRequest();
        break;

case 'tg_menu':
        $tgMenuController = new TelegramMenuController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tgMenuController->processRequest();
        break;

case 'tg_msg':
        $tgMsgController = new TelegramMessageController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tgMsgController->processRequest();
	break;

case 'tg_chat':
        $tgChatController = new TelegramChatController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $tgChatController->processRequest();
	break;

case 'tg_webhook':
    $tgWebhookController = new TelegramWebhookController(
        $dbh,
        $dbhr,
        $requestMethod,
        $param1, // could be the <raw_bot_token>
        $param2,
        $param3,
        $param4,
        $created_by,
        $auth_data
    );
    $tgWebhookController->processRequest();
    break;

case 'test':
      $testController = new TestController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $testController->processRequest();
      break;

 /**
 *
 * end of new telegram webhook apis
 */

case 'blacklist':
      $blController = new BlackListController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $blController->processRequest();
      break;
case 'nreports':
      $ccReportController = new CallCenterReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $ccReportController->processRequest();
      break;

case 'enreports':
      $extReportController = new ExtendedReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $extReportController->processRequest();
      break;

case 'areports':
      $advReportController = new AdvancedReportController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $advReportController->processRequest();
      break;
// Billing System Routes
case 'billing':
      $billingController = new BillingController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $billingController->processRequest();
      break;

// Hasab API Routes
case 'hasab':
      $hasabApiController = new HasabApiController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $hasabApiController->processRequest();
      break;

// API Key Management Routes - param1 is cust_id
case 'api_key':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for API Key management']);
          exit();
      }
      $apiKeyController = new ApiKeyController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $apiKeyController->processRequest();
      break;
// OutDial Campaign Routes - param1 is cust_id
case 'od_campaign':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for OutDial campaigns']);
          exit();
      }
      $outDialCampaignController = new OutDialCampaignController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialCampaignController->processRequest();
      break;

// OutDial Target Routes - param1 is cust_id
case 'od_target':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for OutDial targets']);
          exit();
      }
      $outDialTargetController = new OutDialTargetController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialTargetController->processRequest();
      break;

// OutDial Pool Routes - param1 is cust_id
case 'od_pool':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for OutDial pool']);
          exit();
      }
      $outDialPoolController = new OutDialPoolController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialPoolController->processRequest();
      break;

// OutDial Usage Routes - param1 is cust_id
case 'od_usage':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for OutDial usage']);
          exit();
      }
      $outDialUsageController = new OutDialUsageController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialUsageController->processRequest();
      break;

// OutDial Survey Response Routes - param1 is cust_id
case 'od_response':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for OutDial survey responses']);
          exit();
      }
      $outDialTargetController = new OutDialTargetController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialTargetController->processRequest();
      break;
// Customer Balance Routes - param1 is cust_id
case 'balance':
      if (!$param1 || !is_numeric($param1)) {
          header("HTTP/1.1 400 Bad Request");
          echo json_encode(['error' => 'Customer ID is required for balance management']);
          exit();
      }
      $customerBalanceController = new CustomerBalanceController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $customerBalanceController->processRequest();
      break;

// OutDial Pricing Routes
case 'od_pricing':
      $outDialPricingController = new OutDialPricingController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
      $outDialPricingController->processRequest();
      break;

case 'download-queue':
        $downloadQueueController = new DownloadQueueController($dbh, $dbhr, $requestMethod,
                $param1, $param2, $param3, $param4, $created_by, $auth_data);
        $downloadQueueController->processRequest();
	break;

default:
	header("HTTP/1.1 404 $item: Not Found ");
	exit();
	break;
}
$dbh = null;
$dbhr = null;

/**********===============================VERIFY AND DECODE JWT============================**********/
function check_auth($_valid_api_keys, $unauth_resp, $item = null){
	$open_routes = ['tg_webhook'];
	if($item && in_array($item, $open_routes)) {
		return [
                                'is_token_valid' => true,
                                'created_by' => 9999999,
                                'roles' => ['Any' => ["READ_ONLY"]],
                       ];
	}
	// Check for token in query parameter (for batch audio downloads and audio player)
	if (isset($_GET['token']) && !empty($_GET['token'])) {
		error_log("check_auth: Found token in query parameter");
		try {
			// Decode the base64 encoded token
			$decodedToken = base64_decode($_GET['token']);

			// Extract JWT from "Bearer {JWT}" format
			if (preg_match('/Bearer\s(\S+)/', $decodedToken, $matches)) {
				$jwt = $matches[1];
				error_log("check_auth: Extracted JWT from query parameter");
				$response = verify_and_decode_jwt($jwt, $unauth_resp);
				if ($response['is_token_valid']) {
					error_log("check_auth: Query parameter token validated successfully");
					return $response;
				}
			}
		} catch (Exception $e) {
			error_log("check_auth: Error processing query parameter token: " . $e->getMessage());
		}
	}
	//$headers = json_decode(json_encode(getallheaders()), true);
	$headers = json_decode(json_encode(getallheaders()), true);

	// Preferred header: Authorization: ApiKey <key>
	if (isset($headers['Authorization']) || isset($headers['authorization'])) {
		$authHeader = $headers['Authorization'] ?? $headers['authorization'];
		if (preg_match('/^ApiKey\s+(\S+)/i', $authHeader, $m)) {
			$dbResp = verify_db_api_key($m[1], $unauth_resp, $item);
			if ($dbResp['is_token_valid']) return $dbResp;
			// else fall through to legacy paths
		}
	}

	// Back-compat: X-API-KEY first tries DB, then static list
	if (isset($_SERVER['HTTP_X_API_KEY'])) {
		$dbResp = verify_db_api_key($_SERVER['HTTP_X_API_KEY'], $unauth_resp, $item);
		if ($dbResp['is_token_valid']) return $dbResp;

		// legacy static keys (UNTOUCHED)
		if (in_array($_SERVER['HTTP_X_API_KEY'], $_valid_api_keys)) {
			return [
				'is_token_valid' => true,
				'created_by' => 999999,
				'roles' => ['Any' => ["SUPER_ADMIN"]],
			];
		} else {
			return $unauth_resp;
		}
	}

	if (isset($headers['Authorization']) || isset($headers['authorization'])){
		$authHeader = $headers['Authorization'] ?? $headers['authorization'];
	} else {
		return $unauth_resp;
	}
	preg_match('/Bearer\s(\S+)/', $authHeader, $matches);
	$jwt = $matches[1];
	$response =  verify_and_decode_jwt($jwt, $unauth_resp);
	return $response;
}
function verify_and_decode_jwt($token, $unauth_resp){
	$delimiter = '.';
	list($header, $payload, $signature) = explode($delimiter, $token);
	$to_be_decoded = $payload;
	$jsonToken = base64_decode($to_be_decoded);
	$arrayToken = json_decode($jsonToken, true);

	$expires_at = isset($arrayToken['exp']) ? $arrayToken['exp'] : time() - 60;
	$nowis = time();
	$is_token_expired = ($expires_at - $nowis) < 0;

	//building the signature from header and payload.

	$pubkey = file_get_contents('oauth_signatures/oauth-public.key');
	$signature = base64_decode(strtr($signature, '-_', '+/'));
	$payload_to_verify = utf8_decode($header . $delimiter . $payload);
	$ok_verified = openssl_verify($payload_to_verify, $signature, $pubkey, 'RSA-SHA256');
	if($is_token_expired || !$ok_verified){
		 return $unauth_resp;
	 } else {
		 return [
		 	'is_token_valid' => true,
			'created_by' => $arrayToken['user_id'],
			'roles' => $arrayToken['roles']
		 ];
	 }
}

function verify_db_api_key($rawKey, $unauth_resp, $item=null) {
    // Expect format: ak_{env}_{custId}_{timestamp}_{random}_{chunks}
    // Extract prefix: ak_{env}_{custId}_{timestamp}_{random}_
    if (!preg_match('/^(ak_[a-z]+_\d+_[a-f0-9]+_[a-f0-9]+_)/i', $rawKey, $pm)) {
        //error_log("verify_db_api_key : $rawKey not matched");
        return $unauth_resp;
    }
    $prefix = $pm[1];

    if (!class_exists('ApiKeyData')) {
        require_once('/usr/share/php/v2/ApiKeyData.php');
    }
    global $dbh, $dbhr;
    $ak = new ApiKeyData($dbh, $dbhr);

    $row = $ak->getRowForVerifyByPrefix($prefix);
    if (!$row) {
        error_log("verify_db_api_key : No row found for prefix: $prefix");
        return $unauth_resp;
    }
    error_log("verify_db_api_key : Found row for prefix: $prefix");

    // status & expiry checks
    if ($row['status'] !== 'active') return $unauth_resp;
    if (!empty($row['expires_at']) && strtotime($row['expires_at']) < time()) {
        $dbh->prepare("UPDATE api_keys SET status='expired' WHERE id=:id")->execute([':id'=>$row['id']]);
        $ak->audit($row['id'], 'expired', null, getRealClientIP(), $_SERVER['HTTP_USER_AGENT'] ?? null);
        return $unauth_resp;
    }

    // optional IP allowlist
    if (!empty($row['allowed_ip_ranges'])) {
        $ip = getRealClientIP();
        error_log("verify_db_api_key ip addr is : $ip");
        $ok = false;
        foreach (explode(',', $row['allowed_ip_ranges']) as $cidr) {
            $cidr = trim($cidr);
            if ($cidr === '') continue;
            if (ipInCidr($ip, $cidr)) { $ok = true; break; }
        }
        error_log("verify_db_api_key ip address is allowed : $ok");
        if (!$ok) {
            $ak->audit($row['id'], 'scope_mismatch', ['reason'=>'ip_not_allowed','ip'=>$ip], $ip, $_SERVER['HTTP_USER_AGENT'] ?? null);
            return $unauth_resp;
        }
    }

    // verify full key vs stored hash
    if (!ApiKeyData::verifyRawKeyUsingRow($rawKey, $row)) {
        error_log("verify_db_api_key : Key verification failed for prefix: $prefix");
        return $unauth_resp;
    }
    error_log("verify_db_api_key : Key verification successful for prefix: $prefix");

    $ak->markUsed($row['id']);
    $ak->audit($row['id'], 'used', ['item'=>$item, 'uri'=>($_SERVER['REQUEST_URI'] ?? '')], getRealClientIP(), $_SERVER['HTTP_USER_AGENT'] ?? null);

    $custId = (int)$row['cust_id'];
    $roles  = $row['roles_json'] ? json_decode($row['roles_json'], true) : ["READ_ONLY"];
    return [
        'is_token_valid' => true,
        'created_by' => 900000000 + (int)$row['id'],   // synthetic service user id
        'roles' => ["C:$custId" => $roles]
    ];
}

// Get real client IP from proxy headers
function getRealClientIP() {
    // Multi-hop proxy chain (X-Forwarded-For)
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $parts = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
        foreach ($parts as $ip) {
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
            // if you also want to allow RFC1918 origins through, drop the flags:
            // if (filter_var($ip, FILTER_VALIDATE_IP)) return $ip;
        }
    }

    // Single-hop hint from proxy
    if (!empty($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP)) {
        return $_SERVER['HTTP_X_REAL_IP'];
    }

    // Fallback to REMOTE_ADDR
    return $_SERVER['REMOTE_ADDR'] ?? '';
}

// IPv4 helper
function ipInCidr($ip, $cidr) {
    if (strpos($cidr, '/') === false) return $ip === $cidr;
    list($subnet, $mask) = explode('/', $cidr, 2);
    $mask = (int)$mask;
    return ((ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet));
}

/**********===============================EOF VERIFY AND DECODE============================**********/


?>
