<?php
namespace {
    if (!defined('WD')) {
        define('WD', dirname(__DIR__, 2));
    }

    // Mocking some globals
    global $response, $router, $DEBUG;
    $DEBUG = true;
    $_SERVER['REQUEST_URI'] = '/auth/register/cvr';
    $_SERVER['REQUEST_METHOD'] = 'POST';
}

// Mock response class in classes namespace
namespace classes {
    class MockExitException extends \Error {}

    class response {
        public static $last_success = null;
        public static $last_error = null;
        public static $last_status = null;
        public static $request_parameters = [];

        public static function reset() {
            self::$last_success = null;
            self::$last_error = null;
            self::$last_status = null;
            self::$request_parameters = [];
        }

        public function success($data, $status = 200) {
            self::$last_success = $data;
            self::$last_status = $status;
            throw new MockExitException("SUCCESS_EXIT");
        }

        public function error($data, $status = 400) {
            self::$last_error = $data;
            self::$last_status = $status;
            throw new MockExitException("ERROR_EXIT");
        }

        public function getRequestParameter($key) {
            return self::$request_parameters[$key] ?? null;
        }

        public function isRequestParameterSet($key) {
            return array_key_exists($key, self::$request_parameters);
        }
    }
}

// Mock other dependencies in classes namespace
namespace classes {
    class recaptcha {
        public static $mock_valid = true;
        public function validate($response) { return self::$mock_valid; }
    }

    class economic {
        public static $mock_collection = [];
        public $customers;
        public function __construct() {
            $this->customers = new \stdClass();
            $this->customers->customers = new class {
                public function search($params, $options) {
                    $mock = new \stdClass();
                    $mock->collection = \classes\economic::$mock_collection;
                    return $mock;
                }
            };
        }
        public function createCustomer($number, $name, $cvr, $email, $phone) {
            return ['customerNumber' => $number];
        }
    }

    class virkdata {
        public function getCompanyInformation($cvr, $endpoint, $data) {
            $res = new \stdClass();
            $res->name = "Mock Company";
            return $res;
        }
    }

    class email {
        public function sendWelcomeEmailToCustomer($phone, $email) { return true; }
    }

    class authentication {
        public function get_plate_scanner() { return true; }
    }
}

// Mock objects namespace
namespace objects {
    class users_o {
        public static $mock_user_id = null;
        public static $mock_existing_emails = [];
        public static $mock_existing_customer_numbers = [];

        public function getUserByCustomerNumber($num) {
            $user = new \stdClass();
            $user->id = in_array($num, self::$mock_existing_customer_numbers) ? 1 : self::$mock_user_id;
            return $user;
        }
        public function getUserByEmail($email) {
            $user = new \stdClass();
            $user->id = in_array($email, self::$mock_existing_emails) ? 1 : self::$mock_user_id;
            return $user;
        }
    }
    class logs_o {
        public function add($module, $action, $status, $user_id, $event, $details) {}
    }
    class tokens_o {
        public function delete($token) {}
    }
    class customer_password_reset_keys_o {
        public static function generateToken() { return 'mock_token'; }
        public function add($data) {}
        public function findValidByToken($token) { return null; }
    }
}

// Global namespace mock for router
namespace {
    class MockRouter {
        public $routes = [];
        public function add($route, $method, $callback, $permissions) {
            $this->routes[$method][$route] = $callback;
        }
    }

    $router = new MockRouter();
    $response = new \classes\response();

    // Now include the route
    // We need to bypass the real classes by having them already "loaded" via our mocks above
    // Since we are in the same process and defined them in the same namespaces, 
    // when authRoute.php says "use classes\economic", it will use our mock.

    require_once WD . '/traits/route_t.php';
    require_once WD . '/routes/authRoute.php';

    use routes\authRoute;

    function ok($message): void { echo "\033[32m✔ $message\033[0m\n"; }
    function fail($message): void { echo "\033[31m✖ $message\033[0m\n"; }

    $authRoute = new authRoute();
    $authRoute->run();

    if (!isset($router->routes['POST']['/auth/register/cvr'])) {
        die("Route /auth/register/cvr not found\n");
    }
    $callback = $router->routes['POST']['/auth/register/cvr'];

    $testCases = [
        [
            'name' => 'Missing reCAPTCHA',
            'params' => [],
            'setup' => function() {
                \classes\recaptcha::$mock_valid = false;
            },
            'expected_error' => 'Authentication failed. Invalid or missing reCAPTCHA.',
            'expected_status' => 401
        ],
        [
            'name' => 'Missing parameters',
            'params' => ['g_recaptcha_response' => 'valid'],
            'expected_error' => 'Missing required parameters: cvr, companyPhone, invoiceEmail, contactEmail, contactPhone',
            'expected_status' => 400
        ],
        [
            'name' => 'Invalid CVR length (too short)',
            'params' => [
                'cvr' => '123',
                'companyPhone' => 12345678,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'expected_error' => 'Parameter cvr must be at least 8 characters long',
            'expected_status' => 400
        ],
        [
            'name' => 'Invalid CVR length (too long)',
            'params' => [
                'cvr' => str_repeat('1', 21),
                'companyPhone' => 12345678,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'expected_error' => 'Parameter cvr must be at most 20 characters long',
            'expected_status' => 400
        ],
        [
            'name' => 'Invalid Company Phone (too small)',
            'params' => [
                'cvr' => '12345678',
                'companyPhone' => 9999999,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'expected_error' => 'Parameter must be at least 10000000',
            'expected_status' => 400
        ],
        [
            'name' => 'Existing Company Phone',
            'params' => [
                'cvr' => '12345678',
                'companyPhone' => 12345678,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'setup' => function() {
                \objects\users_o::$mock_existing_customer_numbers = [12345678];
            },
            'expected_error' => 'Company phone number already registered',
            'expected_status' => 400
        ],
        [
            'name' => 'CVR already registered in E-conomic',
            'params' => [
                'cvr' => '12345678',
                'companyPhone' => 12345678,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'setup' => function() {
                \objects\users_o::$mock_user_id = null;
                \classes\economic::$mock_collection = ['something'];
            },
            'expected_error' => 'CVR already registered',
            'expected_status' => 400
        ],
        [
            'name' => 'Successful Registration',
            'params' => [
                'cvr' => '12345678',
                'companyPhone' => 12345678,
                'invoiceEmail' => 'test@test.com',
                'contactEmail' => 'test@test.com',
                'contactPhone' => 12345678,
                'g_recaptcha_response' => 'valid'
            ],
            'setup' => function() {
                \objects\users_o::$mock_user_id = null;
                \classes\economic::$mock_collection = [];
            },
            'expected_success' => ['customerNumber' => 12345678],
            'expected_status' => 201
        ]
    ];

    $allPassed = true;
    foreach ($testCases as $test) {
        \classes\response::reset();
        \classes\recaptcha::$mock_valid = true;
        \objects\users_o::$mock_user_id = null;
        \objects\users_o::$mock_existing_emails = [];
        \objects\users_o::$mock_existing_customer_numbers = [];
        \classes\economic::$mock_collection = [];
        if (isset($test['setup'])) {
            $test['setup']();
        }
        \classes\response::$request_parameters = $test['params'];

        try {
            $callback();
            fail($test['name'] . " - Callback did not exit as expected");
            $allPassed = false;
        } catch (\classes\MockExitException $e) {
            if (isset($test['expected_error'])) {
                if (\classes\response::$last_error === $test['expected_error']) {
                    if (\classes\response::$last_status === $test['expected_status']) {
                        ok($test['name']);
                    } else {
                        fail($test['name'] . " - Expected status " . $test['expected_status'] . " but got " . \classes\response::$last_status);
                        $allPassed = false;
                    }
                } else {
                    fail($test['name'] . " - Expected error '" . $test['expected_error'] . "' but got '" . (\classes\response::$last_error ?? 'NULL') . "'");
                    $allPassed = false;
                }
            } elseif (isset($test['expected_success'])) {
                if (\classes\response::$last_success == $test['expected_success']) {
                    if (\classes\response::$last_status === $test['expected_status']) {
                        ok($test['name']);
                    } else {
                        fail($test['name'] . " - Expected status " . $test['expected_status'] . " but got " . \classes\response::$last_status);
                        $allPassed = false;
                    }
                } else {
                    fail($test['name'] . " - Expected success data " . json_encode($test['expected_success']) . " but got " . json_encode(\classes\response::$last_success));
                    $allPassed = false;
                }
            }
        } catch (\Exception $e) {
            fail($test['name'] . " - Unexpected exception: " . $e->getMessage() . "\n" . $e->getTraceAsString());
            $allPassed = false;
        }
    }

    echo "\nRegisterCvrTest completed.\n";
    exit($allPassed ? 0 : 1);
}
