<?php
/**
 * DMS Application - API/HTTP Endpoint Tests
 * Version: 1.0
 * Date: 2026-02-10
 * 
 * Tests actual HTTP endpoints with authentication
 * Requires cURL extension
 * 
 * Usage: php api_tests.php
 */

// Test Configuration
define('BASE_URL', 'http://localhost/dmsnew/');
define('COOKIE_FILE', sys_get_temp_dir() . '/dms_test_cookies.txt');

class ApiTester {
    private $session_cookies = '';
    private $last_response = null;
    private $current_user = null;
    
    private $results = [
        'passed' => 0,
        'failed' => 0,
        'tests' => []
    ];
    
    /**
     * Make HTTP GET request
     */
    public function get($endpoint, $params = []) {
        $url = BASE_URL . $endpoint;
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }
        return $this->request('GET', $url);
    }
    
    /**
     * Make HTTP POST request
     */
    public function post($endpoint, $data = []) {
        return $this->request('POST', BASE_URL . $endpoint, $data);
    }
    
    /**
     * Core HTTP request handler
     */
    private function request($method, $url, $data = []) {
        $ch = curl_init();
        
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HEADER => true,
            CURLOPT_COOKIEJAR => COOKIE_FILE,
            CURLOPT_COOKIEFILE => COOKIE_FILE,
            CURLOPT_USERAGENT => 'DMS Test Suite/1.0',
            CURLOPT_TIMEOUT => 30
        ]);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        }
        
        $response = curl_exec($ch);
        $info = curl_getinfo($ch);
        $error = curl_error($ch);
        curl_close($ch);
        
        $header_size = $info['header_size'];
        $headers = substr($response, 0, $header_size);
        $body = substr($response, $header_size);
        
        $this->last_response = [
            'url' => $url,
            'method' => $method,
            'http_code' => $info['http_code'],
            'headers' => $headers,
            'body' => $body,
            'error' => $error,
            'total_time' => $info['total_time']
        ];
        
        return $this->last_response;
    }
    
    /**
     * Login as a user
     */
    public function login($email, $password) {
        // Clear previous session
        if (file_exists(COOKIE_FILE)) {
            unlink(COOKIE_FILE);
        }
        
        $response = $this->post('login/secureLogin', [
            'user_email' => $email,
            'user_password' => $password
        ]);
        
        // Check if redirected to dashboard (success) or back to login (failure)
        $success = strpos($response['body'], 'dashboard') !== false || 
                   strpos($response['headers'], 'Location: ' . BASE_URL . 'dashboard') !== false ||
                   $response['http_code'] == 302;
        
        if ($success) {
            $this->current_user = $email;
        }
        
        return $success;
    }
    
    /**
     * Logout current user
     */
    public function logout() {
        $this->get('login/logout');
        $this->current_user = null;
        if (file_exists(COOKIE_FILE)) {
            unlink(COOKIE_FILE);
        }
    }
    
    /**
     * Assert test result
     */
    public function assert($condition, $test_name, $message = '') {
        if ($condition) {
            $this->results['passed']++;
            $status = '✅ PASS';
        } else {
            $this->results['failed']++;
            $status = '❌ FAIL';
        }
        
        $full_message = "$status: $test_name" . ($message ? " - $message" : "");
        echo $full_message . "\n";
        
        $this->results['tests'][] = [
            'name' => $test_name,
            'passed' => $condition,
            'message' => $message
        ];
        
        return $condition;
    }
    
    /**
     * Check if response contains text
     */
    public function responseContains($text) {
        return strpos($this->last_response['body'], $text) !== false;
    }
    
    /**
     * Check HTTP status code
     */
    public function statusIs($code) {
        return $this->last_response['http_code'] == $code;
    }
    
    /**
     * Get last response
     */
    public function getLastResponse() {
        return $this->last_response;
    }
    
    /**
     * Print test summary
     */
    public function summary() {
        $total = $this->results['passed'] + $this->results['failed'];
        $rate = $total > 0 ? round($this->results['passed'] / $total * 100, 2) : 0;
        
        echo "\n" . str_repeat("=", 60) . "\n";
        echo "📊 API TEST SUMMARY\n";
        echo str_repeat("=", 60) . "\n";
        echo "Total Tests: $total\n";
        echo "Passed: {$this->results['passed']} ✅\n";
        echo "Failed: {$this->results['failed']} ❌\n";
        echo "Success Rate: {$rate}%\n";
        echo str_repeat("=", 60) . "\n";
    }
    
    /**
     * Section header
     */
    public function section($title) {
        echo "\n" . str_repeat("=", 60) . "\n";
        echo "📋 $title\n";
        echo str_repeat("=", 60) . "\n";
    }
    
    /**
     * Info message
     */
    public function info($message) {
        echo "ℹ️  $message\n";
    }
}

// =====================================================
// TEST SCENARIOS
// =====================================================

$api = new ApiTester();

echo "\n";
echo "╔══════════════════════════════════════════════════════════╗\n";
echo "║       DMS APPLICATION - API/HTTP ENDPOINT TESTS         ║\n";
echo "╚══════════════════════════════════════════════════════════╝\n";
echo "\n";
echo "Base URL: " . BASE_URL . "\n";
echo "Started: " . date('Y-m-d H:i:s') . "\n";

// =====================================================
// AUTHENTICATION TESTS
// =====================================================
$api->section("AUTHENTICATION TESTS");

// Test login page accessible
$response = $api->get('login');
$api->assert($api->statusIs(200), "Login Page Accessible");

// Test invalid login
$api->login('invalid@test.com', 'wrongpassword');
$api->assert(!$api->responseContains('dashboard'), "Invalid Login Rejected");

// Test Super Admin login
$login_success = $api->login('superadmin@dms.com', 'Admin@123');
$api->assert($login_success, "Super Admin Login", "superadmin@dms.com");

// Test dashboard access after login
$response = $api->get('dashboard/dashboard');
$api->assert($api->statusIs(200), "Dashboard Accessible After Login");

$api->logout();

// =====================================================
// SUPER ADMIN ACCESS TESTS
// =====================================================
$api->section("SUPER ADMIN ACCESS TESTS");

$api->login('superadmin@dms.com', 'Admin@123');

// Company access
$response = $api->get('company/companies');
$api->assert($api->statusIs(200), "Super Admin - Company List Access");

// User management access
$response = $api->get('user/users');
$api->assert($api->statusIs(200), "Super Admin - User List Access");

// Authority access
$response = $api->get('authority/viewAuthority');
$api->assert($api->statusIs(200), "Super Admin - Authority List Access");

// Document Head access
$response = $api->get('type/allType');
$api->assert($api->statusIs(200), "Super Admin - Document Head List Access");

// Holiday access
$response = $api->get('holiday');
$api->assert($api->statusIs(200), "Super Admin - Holiday List Access");

// Reminder Report access
$response = $api->get('reminder/report');
$api->assert($api->statusIs(200), "Super Admin - Reminder Report Access");

$api->logout();

// =====================================================
// ADMIN ACCESS TESTS
// =====================================================
$api->section("ADMIN ACCESS TESTS");

$api->login('admin.alpha@test.com', 'Admin@123');

// Dashboard access
$response = $api->get('dashboard/dashboard');
$api->assert($api->statusIs(200), "Admin Alpha - Dashboard Access");

// Company list (should only see assigned companies)
$response = $api->get('company/companies');
$api->assert($api->statusIs(200), "Admin Alpha - Company List Access");
$api->assert(
    $api->responseContains('Alpha') || $api->responseContains('Beta'),
    "Admin Alpha - Can See Assigned Companies"
);

$api->logout();

// Test Admin Gamma (without delete permission)
$api->login('admin.gamma@test.com', 'Admin@123');

$response = $api->get('dashboard/dashboard');
$api->assert($api->statusIs(200), "Admin Gamma - Dashboard Access");

$api->logout();

// =====================================================
// USER (ROLE 3) ACCESS TESTS
// =====================================================
$api->section("USER ROLE ACCESS TESTS");

// View-Only User
$api->login('user.viewonly@test.com', 'User@123');

$response = $api->get('dashboard/dashboard');
$api->assert($api->statusIs(200), "View-Only User - Dashboard Access");

// Should not see user management
$response = $api->get('user/users');
$has_permission_error = $api->responseContains('permission') || 
                        $api->responseContains('access') ||
                        $api->statusIs(403) ||
                        strpos($api->getLastResponse()['headers'], 'Location') !== false;
// View-only users should have restricted access to user management
$api->info("View-Only User - User Management response code: " . $api->getLastResponse()['http_code']);

$api->logout();

// Editor User
$api->login('user.editor@test.com', 'User@123');

$response = $api->get('dashboard/dashboard');
$api->assert($api->statusIs(200), "Editor User - Dashboard Access");

$api->logout();

// =====================================================
// API ENDPOINT TESTS
// =====================================================
$api->section("API ENDPOINT TESTS");

$api->login('superadmin@dms.com', 'Admin@123');

// Dashboard counts API
$response = $api->get('dashboard/getCounts');
$api->assert($api->statusIs(200), "Dashboard Counts API");
$is_json = json_decode($api->getLastResponse()['body']) !== null;
$api->assert($is_json, "Dashboard Counts Returns JSON");

// Get tab data API
$response = $api->post('dashboard/getTabData', ['tab' => 'favourite']);
$api->assert($api->statusIs(200), "Get Tab Data API (Favourites)");

$response = $api->post('dashboard/getTabData', ['tab' => 'pending']);
$api->assert($api->statusIs(200), "Get Tab Data API (Pending)");

// Favourite status API
$response = $api->get('dashboard/getFavouriteStatus');
$api->assert($api->statusIs(200), "Favourite Status API");

$api->logout();

// =====================================================
// RBAC RESTRICTION TESTS
// =====================================================
$api->section("RBAC RESTRICTION TESTS");

// Test that logged-out user cannot access protected pages
$response = $api->get('dashboard/dashboard');
$redirected_to_login = strpos($api->getLastResponse()['headers'], 'login') !== false ||
                       $api->responseContains('login');
$api->assert($redirected_to_login, "Unauthenticated User Redirected to Login");

// Test Admin cannot access other admin's companies
$api->login('admin.alpha@test.com', 'Admin@123');

// Try to access a company not assigned to this admin (company 3 = Gamma)
// This test depends on the company IDs in database
$response = $api->get('company/viewDocuments/3');
$api->info("Admin Alpha accessing Gamma Solutions - Response: " . $api->getLastResponse()['http_code']);

$api->logout();

// =====================================================
// FORM SUBMISSION TESTS
// =====================================================
$api->section("FORM SUBMISSION TESTS");

$api->login('superadmin@dms.com', 'Admin@123');

// Test company name check (AJAX)
$response = $api->post('company/checkCompanyName', [
    'company_name' => 'Test Company ' . time()
]);
$api->assert($api->statusIs(200), "Company Name Check API");

// Test get authorities by company (AJAX)
$response = $api->post('user/getAuthoritiesByCompanies', [
    'company_ids' => [1]
]);
$api->assert($api->statusIs(200), "Get Authorities by Company API");

$api->logout();

// =====================================================
// SECURITY TESTS
// =====================================================
$api->section("SECURITY TESTS");

// Test CSRF protection (if implemented)
$api->login('superadmin@dms.com', 'Admin@123');

// Test SQL injection prevention in search
$response = $api->get('company/companies', [
    'search' => "'; DROP TABLE company; --"
]);
$api->assert($api->statusIs(200), "SQL Injection Prevention", "Search parameter sanitized");

// Test XSS prevention
$response = $api->get('company/companies', [
    'search' => '<script>alert("xss")</script>'
]);
$api->assert(!$api->responseContains('<script>alert'), "XSS Prevention", "Script tags sanitized");

$api->logout();

// =====================================================
// PERFORMANCE TESTS
// =====================================================
$api->section("PERFORMANCE TESTS");

$api->login('superadmin@dms.com', 'Admin@123');

// Dashboard load time
$response = $api->get('dashboard/dashboard');
$load_time = $api->getLastResponse()['total_time'];
$api->assert($load_time < 5, "Dashboard Load Time", sprintf("%.2f seconds", $load_time));

// API response time
$response = $api->get('dashboard/getCounts');
$api_time = $api->getLastResponse()['total_time'];
$api->assert($api_time < 2, "API Response Time", sprintf("%.2f seconds", $api_time));

$api->logout();

// =====================================================
// SUMMARY
// =====================================================
$api->summary();

echo "\nCompleted: " . date('Y-m-d H:i:s') . "\n";

// Cleanup
if (file_exists(COOKIE_FILE)) {
    unlink(COOKIE_FILE);
}

