<?php

namespace routes;

use classes\authentication;
use objects\customer_vehicles_o;
use objects\logs_o;
use objects\orders_o;
use objects\plate_scans_o;
use objects\users_o;
use traits\route_t;

class plateScansRoute
{
    use route_t;

    public function run(): void
    {

        $this->post('/numberplatescans', function () {
            // Require the user to be logged in
            global $response;
            $this->requirePlateScannerAuth();
            // Get the plate scanner object
            $plate_scanner = (new authentication())->get_plate_scanner();
            /**
             * Define the optional request body parameters
             * - plate: The license plate to scan (string, required)
             * - bayId: The wash bay id (int, optional) - XLVASK lanes only
             */
            $bayId = null;
            // Validate the bayId if set
            $bayIdParameterKey = 'bay_id';
            if (self::isParametersSet([$bayIdParameterKey])) {
                $bayId = self::getParameter($bayIdParameterKey);
                self::requireType($bayId, self::type_string());
                self::requireMinLength($bayIdParameterKey, 1);
                self::requireMaxLength($bayIdParameterKey, 255);
            }
            // Get the post data
            $data = json_decode(file_get_contents('php://input'), true);
            // Check if the required fields are set
            if (!isset($data['plate'])) {
                $response->error('Missing required body parameter plate', 400);
            }
            // Add the number plate scanner
            (new plate_scans_o())->add($plate_scanner->id, $data['plate'], $bayId);
            // Log the incident
            (new logs_o())->add('numberplatescans', $plate_scanner->department_id->value(), 1, 0, 'ADD_NUMBER_PLATE_SCANS', 'Successfully added a number plate scan: ' . $data['plate']);
            // Return a success message
            $response->success(['message' => 'License plate scan recorded.', 'plate' => $data['plate'], 'scanner' => $plate_scanner->name->value(), 'bay_id' => $bayId], 201);
        });

        $this->post('/numberplatescans/department', function () {
            // Require the user to be logged in
            global $response;
            $this->requirePermission('list_number_plate_scans_department');
            // Get the user object
            $user = (new authentication())->get_user();
            // Check if the request was successful
            if ($user) {
                // Check if a department is set in the body
                $data = json_decode(file_get_contents('php://input'), true);
                if (!isset($data['department_id'])) {
                    $response->error('Missing required body parameter department', 400);
                }
                $this->requirePermission('list_number_plate_scans_department_' . $data['department_id']);
                // Check if the pagination parameters are set
                if (!isset($data['page'])) {
                    $response->error('Missing required body parameter page', 400);
                }
                if (!isset($data['limit'])) {
                    $response->error('Missing required body parameter limit', 400);
                }
                // Get the number plate scans
                $number_plate_scans = (new plate_scans_o())->getPlateScansByDepartment((int)$data['department_id'], (int)$data['page'], (int)$data['limit']);
                // Log the incident
                (new logs_o())->add('numberplatescans', $data['department_id'], 1, $user->id, 'LIST_NUMBER_PLATE_SCANS_DEPARTMENT', 'Successfully listed number plate scans for department: ' . $data['department_id']);
                // Return the number plate scans
                $response->success($number_plate_scans);
            } else {
                // Log the incident
                (new logs_o())->add('numberplatescans', 'global', 1, 0, 'LIST_NUMBER_PLATE_SCANS_DEPARTMENT', 'No user found, or invalid session');
                // Return an error
                $response->error('Invalid session', 400);
            }
        }, [
            'list_number_plate_scans_department' => 'List all number plate scans for a department'
        ]);

        $this->get('/numberplatescans', function () {
            // Require the user to be logged in
            global $response;
            $this->requirePermission('list_number_plate_scans');
            // Get the user object
            $user = (new authentication())->get_user();
            // Check if the request was successful
            if ($user) {
                // Get the number plate scans
                $number_plate_scans = (new plate_scans_o());
                $result = $number_plate_scans->listObjectsWithPaginationIfSet(
                    function ($scan) {
                        $tmp_scan_seen_before = [
                            'seen_before' => (new orders_o())->isPlateSeenBefore((string)$scan['plate']),
                        ];
                        $tmp_scan_customer = [
                            'barred' => false,
                            'customer_number' => null,
                            'customer_name' => null,
                        ];
                        // Check if the vehicle is registered to a customer
                        $vehicle_customer_number = (new customer_vehicles_o())->getPlateCustomerNumber((string)$scan['plate']);
                        if ($vehicle_customer_number) {
                            // Get the vehicle details
                            $tmp_scan_vehicle = (new customer_vehicles_o())->selectByPlate((string)$scan['plate'])->asArray();
                            $tmp_scan_customer = [
                                'barred' => (new users_o())->isCustomerBarred($vehicle_customer_number),
                                'customer_number' => (int)$vehicle_customer_number,
                                'customer_name' => $tmp_scan_vehicle['customer_name'],
                                'type' => (int)$tmp_scan_vehicle['type'],
                            ];
                        }
                        // Return the object as an array
                        return [
                            ...$scan,
                            ...$tmp_scan_customer,
                            ...$tmp_scan_seen_before,
                        ];
                    },
                    $number_plate_scans->forceRestrictFilters(
                        [
                            'department_id' => $user->getGroup()->getDepartments()
                        ]
                    )
                );
                // Log the incident
                (new logs_o())->add('numberplatescans', 'global', 1, $user->id, 'LIST_NUMBER_PLATE_SCANS', 'Successfully listed number plate scans');
                // Return the number plate scans
                $response->success($result);
            } else {
                // Log the incident
                (new logs_o())->add('numberplatescans', 'global', 1, 0, 'LIST_NUMBER_PLATE_SCANS', 'No user found, or invalid session');
                // Return an error
                $response->error('Invalid session', 400);
            }
        }, [
            'list_number_plate_scans' => 'List all number plate scans, provided the user has access to the department the number plate scan is in',
            'department_access_:id' => 'Access to the department the number plate scan is in'
        ]);

        self::get('/numberplatescans/post', function () {
            /**
             * This is here because the post method is not supported by the software some of the cameras are running on.
             */
            global $response;
            self::requirePlateScannerAuth();
            $plate_scanner = (new authentication())->get_plate_scanner();
            self::requireParameters(['plate', 'token']);
            // Validate the plate
            self::requireType('plate', 'string');
            self::requireMinLength('plate', 1);
            self::requireMaxLength('plate', 10);
            // Validate the token
            self::requireType('token', 'string');
            self::requireMinLength('token', 1);
            self::requireMaxLength('token', 100);
            // Add the number plate scanner
            (new plate_scans_o())->add($plate_scanner->id, self::getParameter('plate'));
            // Log the incident
            (new logs_o())->add('numberplatescans', $plate_scanner->department_id->value(), 1, 0, 'ADD_NUMBER_PLATE_SCANS', 'Successfully added a number plate scan: ' . self::getParameter('plate'));
            // Return a success message
            $response->success(['message' => 'License plate scan recorded.', 'plate' => self::getParameter('plate'), 'scanner' => $plate_scanner->name->value()], 201);
        }, [
            'add_number_plate_scan' => 'Add a number plate scan'
        ]);
    }
}