<?php

namespace traits;

use classes\response;
use Exception;
use forms\objects\book_wash_f;
use objects\department_variables_o;
use objects\departments_o;
use objects\form_submissions_o;
use objects\users_o;
use routes\formRoute;

trait form_t
{
    /**
     * The form identifier
     * @var string $form_identifier The form identifier
     */
    public string $form_identifier;
    /**
     * The form name
     * @var string $form_name The form name
     */
    public string $form_name;
    /**
     * The form description
     * @var string $form_description The form description
     */
    public string $form_description;
    /**
     * The form sanitized data
     * @var array $form_sanitized_data The form sanitized data
     */
    public array $form_sanitized_data;
    /**
     * The department id, if applicable
     * @notation This should be used to store the department id, if applicable
     * @see setDepartmentId()
     * @see getDepartmentId()
     * @var int|null $department_id The department id
     */
    public int|null $department_id = null;
    /**
     * The user id, if applicable
     * @notation This should be used to store the user id, if applicable
     * @see setUserId()
     * @see getUserId()
     * @var int|null $user_id The user id
     */
    public int|null $user_id = null;
    /**
     * The customer number, if applicable
     * @notation This should be used to store the customer number, if applicable
     * @see setCustomerNumber()
     * @see getCustomerNumber()
     * @var int|null $customer_number The customer number
     */
    public int|null $customer_number = null;
    /**
     * The form fields
     * @notation This should be used to store the form fields and their validation methods
     * @var array $form_fields The form fields and their validation methods (E.g. ['name' => 'self::className()::validateString', 'email' => 'self::className()::validateEmail'])
     * @see defineInputFields()
     * @see requireInputFields()
     * @see validateInput()
     */
    public array $form_fields_validations = [];
    /**
     * The form fields options
     * @notation This should be used to store the form fields options (e.g. ['field1' => ['option1' => 'Option 1', 'option2' => 'Option 2']])
     * @var array $form_fields_options The form fields options
     */
    public array $form_fields_options = [];

    /**
     * The form raw data / unsanitized input values
     * @notation This should be used to store the form raw data (Unsanitized)
     * @var array $form_unsanitized_data
     */
    public array $form_unsanitized_data = [];
    /**
     * The form submissions object (When the form is submitted)
     * @var form_submissions_o $form_submissions_o The form submissions object
     * @see form_submissions_o
     * @see submit()
     */
    public form_submissions_o $form_submissions_o;
    /**
     * The form fields descriptions
     * @var array $form_fields_metas The form fields descriptions
     * @notation This should be used to store the form fields descriptions (e.g. ['field1' => 'Field 1', 'field2' => 'Field 2'])
     * @see getFormFields()
     * @see defineInputFields()
     */
    public array $form_fields_metas = [];
    /**
     * The text displayed on the submit button
     * @var string $submit_button_text The text displayed on the submit button
     * @notation This should be used to store the text displayed on the submit button
     * @see submit()
     * @see setSubmitButtonText()
     * @see getSubmitButtonText()
     */
    public string $submit_button_text = 'Submit';

    /**
     * The form constructor (Runs the setup method)
     * @notation This should be used to set the form identifier, name and description
     * @throws Exception If the form identifier, name or description is empty
     */
    public function __construct()
    {
        parent::__construct();
        self::setup();
    }

    /**
     * The form setup method, this is run when the form is created
     * @throws Exception If the form identifier, name or description is empty
     * @throws Exception If the form identifier is not a valid format (e.g. "FORM_IDENTIFIER")
     */
    abstract public function setup();

    /**
     * The form run method, this is run when the form is submitted
     * @throws Exception If the form input is not valid
     * @throws Exception If the form was not submitted successfully
     */
    public function submit(): void
    {
        // Validate the form identifier, name and description
        self::validate();
        // Require the input fields to be set
        self::requireInputFields();
        // Validate the form input
        self::validateInput();
        // Sanitize the form input
        self::sanitize();
        // Before save function
        self::beforeSave();
        // Save the form input to the database
        self::save();
        // Run the form after successful submission
        self::afterSubmit();
    }

    /**
     * Validate the form identifier, name and description
     * @throws Exception If the form identifier, name or description is empty
     */
    public function validate(): void
    {
        if (empty($this->form_identifier)) {
            throw new Exception('The form identifier is empty');
        }
        if (empty($this->form_name)) {
            throw new Exception('The form name is empty');
        }
        if (empty($this->form_description)) {
            throw new Exception('The form description is empty');
        }
    }

    /**
     * Require input fields to be set
     * @notation This should be used to check if the fields are set and if the input is valid
     * @throws Exception If the input fields callable is not callable, or if the input fields are not set
     * @see defineInputFields()
     * @see validateInput()
     */
    public function requireInputFields(): void
    {
        global /** @var response $response */
        $response;
        $errors = [];
        $missing_fields = [];
        $DATA = json_decode(file_get_contents('php://input'), true);
        foreach ( $this->form_fields_validations as $field => $validation_method ) {
            // Check if the post field is set
            if (!isset($DATA[self::getFormFieldPrefix() . $field])) {
                // Check if the field is required
                if (self::isFieldRequired($field)) {
                    // If the field is required, add it to the missing fields
                    $missing_fields[] = self::getFormFieldPrefix() . $field;
                }
            } else {
                // Check if the field is valid
                if (is_callable($validation_method) || method_exists($this, $validation_method)) {
                    $callable = is_callable($validation_method) ? $validation_method : [$this, $validation_method];
                    try {
                        // Check if the field is multiple ( e.g. ['field1', 'field2'])
                        if (is_array($DATA[self::getFormFieldPrefix() . $field])) {
                            // If there's no value, check if the field is required
                            if (count($DATA[self::getFormFieldPrefix() . $field]) === 0) {
                                // If the field is required, add it to the missing fields
                                if (self::isFieldRequired($field)) {
                                    $missing_fields[] = self::getFormFieldPrefix() . $field;
                                }
                            }
                            // Loop through the array and check if each value is valid
                            foreach ( $DATA[self::getFormFieldPrefix() . $field] as $value ) {
                                // Call the validation method
                                $is_valid = call_user_func($callable, $value);
                                if (!$is_valid) {
                                    // If the value is not valid, add it to the errors
                                    $errors[self::getFormFieldPrefix() . $field] = [
                                        'error' => 'The field is invalid, please check the format',
                                        'field' => self::getFormFieldPrefix() . $field,
                                    ];
                                }
                            }
                        } else {
                            // Call the validation method
                            $is_valid = call_user_func($callable, $DATA[self::getFormFieldPrefix() . $field]);
                        }
                    } catch (Exception $e) {
                        // If the validation method throws an exception, add it to the errors
                        $errors[self::getFormFieldPrefix() . $field] = [
                            'error' => 'The field is invalid, please check the format',
                            'field' => self::getFormFieldPrefix() . $field,
                        ];
                    }
                    if (!$is_valid) {
                        // Check if the value is empty, and the field isn't required
                        // If the field is required, we don't need to add it to the errors
                        // If the field is not required, we need to add it to the errors

                        if (self::isFieldRequired($field)) {
                            // If the value is not valid, add it to the errors
                            $errors[self::getFormFieldPrefix() . $field] = [
                                'error' => 'The field is invalid, please check the format',
                                'field' => self::getFormFieldPrefix() . $field,
                            ];
                        } else if (!self::isFieldRequired($field) && empty($DATA[self::getFormFieldPrefix() . $field])) {
                            // If the value is empty, and the field isn't required, we don't need to add it to the errors
                        } else {
                            // If the value is not valid, add it to the errors
                            $errors[self::getFormFieldPrefix() . $field] = [
                                'error' => 'The field is invalid, please check the format',
                                'field' => self::getFormFieldPrefix() . $field,
                            ];
                        }
                    }
                } else {
                    // Throw an error if the validation method is not callable
                    throw new Exception('The validation method is not callable for field: ' . self::getFormFieldPrefix() . $field . ' - ' . $validation_method);
                }
            }
            // Add the field to the form unsanitized data
            $this->form_unsanitized_data[self::getFormFieldPrefix() . $field] = $DATA[self::getFormFieldPrefix() . $field];
        }
        // Check if any fields are missing
        if (!empty($missing_fields)) {
            foreach ( $missing_fields as $field ) {
                $errors[$field] = [
                    'error' => 'The field is required',
                    'field' => $field,
                ];
            }
        }
        // Check if there are any errors
        if (empty($errors)) {
            // All fields are valid
            return;
        }
        // Return an error
        $response->error(
            [
                'message' => 'Input validation failed',
                'errors' => $errors,
            ],
            400,
        );
    }

    /**
     * Get the form field prefix
     * @return string The form field prefix
     */
    public function getFormFieldPrefix(): string
    {
        return $this->form_identifier . '_field_';
    }

    /**
     * Check if the field is required
     * @param string $field The field to check
     * @return bool True if the field is required, false otherwise
     */
    public function isFieldRequired(string $field): bool
    {
        // Check if the field is required
        if (isset($this->form_fields_metas[$field]['required'])) {
            return $this->form_fields_metas[$field]['required'];
        }
        return false;
    }

    /**
     * The form input validation
     * @notation This should be used to check if the fields are set and if the input is valid
     * @throws Exception If the input is not valid
     */
    abstract public function validateInput(): void;

    /**
     * The form input sanitization
     * @throws Exception If the input is not valid
     */
    abstract public function sanitize(): void;

    /**
     * The form before save method, this is run before the form is saved
     * @throws Exception If the form was not submitted successfully
     */
    abstract public function beforeSave(): void;

    /**
     * Save the form input to the database
     * @throws Exception If the form was not submitted successfully
     */
    public function save(): void
    {
        // Save the form input to the database
        $form_submissions_o = new form_submissions_o;
        $form_submissions_o->add(
            $this->form_identifier,
            $this->form_sanitized_data,
            self::getUserId(),
            self::getDepartmentId(),
            self::getCustomerNumber(),
        );
        // Set the form submissions object
        $this->form_submissions_o = $form_submissions_o;
    }

    /**
     * Get the user id
     * @return int|null The user id
     */
    public function getUserId(): int|null
    {
        return $this->user_id;
    }

    /**
     * Set the user id
     * @param int|null $user_id The user id
     * @return form_t|book_wash_f
     */
    public function setUserId(int|null $user_id): self
    {
        $this->user_id = $user_id;
        return $this;
    }

    /**
     * Get the department id
     * @return int|null The department id
     */
    public function getDepartmentId(): int|null
    {
        return $this->department_id;
    }

    /**
     * Set the department id
     * @param int|null $department_id The department id
     * @return form_t|book_wash_f
     * @throws Exception If the department does not exist
     */
    public function setDepartmentId(int|null $department_id): self
    {
        // If the department id is not set, set it to null
        if (empty($department_id)) {
            $department_id = null;
        }
        // Check if the department exists
        $department = (new departments_o())->selectId($department_id);
        if (!$department->exists()) {
            throw new Exception('The department does not exist');
        }
        // Set the department id
        $this->department_id = $department_id;
        return $this;
    }

    /**
     * Get the customer number
     * @return int|null The customer number
     */
    public function getCustomerNumber(): int|null
    {
        return $this->customer_number;
    }

    /**
     * Set the customer number
     * @param int|null $customer_number The customer number
     * @return form_t|book_wash_f
     * @throws Exception
     */
    public function setCustomerNumber(int|null $customer_number): self
    {
        // If the customer number is not set, set it to null
        if (empty($customer_number)) {
            $customer_number = null;
        }
        // Check if the customer number is valid
        if (!is_numeric($customer_number)) {
            throw new Exception('The customer number is not valid');
        }
        // Check if the customer number exists
        $customer = (new users_o())->getUserByCustomerNumber($customer_number);
        if (!$customer->exists()) {
            throw new Exception('The customer number does not exist');
        }
        // Set the customer number
        $this->customer_number = $customer_number;
        return $this;
    }

    /**
     * The form after successful submission
     */
    abstract public function afterSubmit(): void;

    /**
     * Get the sanitized data key
     * @param string $key The key to get
     * @return mixed The sanitized data
     * @throws Exception If the key is not valid
     */
    public function getSanitizedData(string $key): mixed
    {
        // Check if the key is valid
        if (!isset($this->form_sanitized_data[self::getFormFieldPrefix() . $key])) {
            throw new Exception('The key is not valid: ' . $key);
        }
        // Return the sanitized data
        return $this->form_sanitized_data[self::getFormFieldPrefix() . $key];
    }

    /**
     * Define the form input fields
     * @notation E.g. ['name' => 'self::className()::validateString', 'email' => 'self::className()::validateEmail']
     * @throws Exception If the input fields are not valid
     * @var array $input_fields The form input fields
     */
    public function defineInputFields(array $input_fields): void
    {
        // Set the form input fields
        $fields = [];
        foreach ( $input_fields as $field => $validation_method ) {
            // Check if the field is valid
            if (is_callable($validation_method)) {
                $fields[$field] = $validation_method;
            } else {
                // Throw an error if the validation method is not callable
                throw new Exception('The validation method is not callable for field: ' . $field . ' - ' . $validation_method);
            }
        }
        // Set the form input fields
        $this->form_fields_validations = $fields;
    }

    /**
     * Define the form fields with validation methods, descriptions and options
     * @param array $input_fields The form input fields (e.g. ['name' => ['validation_method' => 'validateString', 'description' => 'Name', 'options' => ['option1' => 'Option 1', 'option2' => 'Option 2']]])
     * @throws Exception If the input fields are not valid
     * @throws Exception If the input fields options are not valid
     * @throws Exception If the input fields metadata are not valid
     */
    public function defineInputFieldsAdvanced(array $input_fields): void
    {
        // Set the form input fields
        $tmp_validators = [];
        $tmp_metas = [];
        $tmp_options = [];
        foreach ( $input_fields as $field => $input_field ) {
            // Check if the field is valid
            if (isset($input_field['validation_method'])) {
                $tmp_validators[$field] = self::className() . '::' . $input_field['validation_method'];
                // We need to remove the validation method from the input field, to avoid adding it to the form fields metas
                unset($input_field['validation_method']);
            } else {
                throw new Exception('The validation method is not valid for field: ' . $field);
            }
            // Check if the field has options
            if (isset($input_field['options'])) {
                $tmp_options[$field] = $input_field['options'];
                // We need to remove the options from the input field, to avoid adding it to the form fields metas
                unset($input_field['options']);
            }
            // Add the prefix to the display condition
            if (isset($input_field['display_if'])) {
                $input_field['display_if'] = self::getFormFieldPrefix() . $input_field['display_if'];
            }
            // Loop through the input fields data
            foreach ( $input_field as $key => $value ) {
                // Add the field key to the form fields metas
                $tmp_metas[$field][$key] = $value;
            }
            // Check if the field has a display condition
        }
        // Set the form input fields
        $this->form_fields_validations = $tmp_validators;
        $this->form_fields_metas = $tmp_metas;
        $this->form_fields_options = $tmp_options;
    }

    /**
     * Get the class name
     * @return string The class name
     */
    public function className(): string
    {
        return get_class($this);
    }

    /**
     * Add options to the form input fields
     * @param string $field The field to add options to
     * @param array $input_fields_options The input fields options (e.g. ['option1' => 'Option 1', 'option2' => 'Option 2'])
     * @throws Exception If the field is not valid
     * @throws Exception If the input fields options are not valid
     * @notation E.g. ['field1' => ['option1' => 'Option 1', 'option2' => 'Option 2']]
     * @throws Exception
     */
    public function addInputFieldOptions(string $field, array $input_fields_options): void
    {
        // Check if the field is valid
        if (!isset($this->form_fields_validations[$field])) {
            throw new Exception('The field is not valid: ' . $field);
        }
        // Check if the input fields options are valid
        if (empty($input_fields_options)) {
            throw new Exception('The input fields options are not valid: ' . $field);
        }
        // Check if the input fields options are valid
        foreach ( $input_fields_options as $option => $value ) {
            // Check if the option is valid
            if (!is_string($value)) {
                throw new Exception('The input fields options are not valid: ' . $field);
            }
        }
        // Check if the field is valid
        if (!isset($this->form_fields_validations[$field])) {
            throw new Exception('The field is not valid: ' . $field);
        }
        // Set the form input fields options
        $this->form_fields_options[$field] = $input_fields_options;
    }

    /**
     * Validation method for emails
     * @param string $email The email to validate
     * @return bool True if the email is valid, false otherwise
     */
    public function validateEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    /**
     * Validation method for phone numbers
     * @param string $phone The phone number to validate
     * @return bool True if the phone number is valid, false otherwise
     */
    public function validatePhone(string $phone): bool
    {
        // Check if the phone number is valid
        // This regex allows for optional '+' at the start, followed by 7 to 15 digits
        return preg_match('/^\+?[0-9]{7,15}$/', $phone) === 1;
    }

    /**
     * Validation method for customer numbers
     * @param int $customer_number The customer number to validate
     * @return bool True if the customer number is valid, false otherwise
     */
    public function validateCustomerNumber(int|string $customer_number): bool
    {
        // Check if the customer number is valid
        // This regex allows for 1 to 10 digits
        return preg_match('/^[0-9]{1,10}$/', $customer_number) === 1;
    }

    /**
     * Validation method for integers
     * @param int $int The integer to validate
     * @return bool True if the integer is valid, false otherwise
     */
    public function validateInt(int $int): bool
    {
        // Check if the integer is valid
        // This regex allows for optional '+' or '-' at the start, followed by 1 to 10 digits
        return preg_match('/^[+-]?[0-9]{1,10}$/', $int) === 1;
    }

    /**
     * Validation method for booking ids
     * @param int $int The integer to validate
     * @return bool True if the integer is valid, false otherwise
     */
    public function validateBookingId(int $int): bool
    {
        // Check if the booking id is valid (A positive integer)
        return preg_match('/^[1-9][0-9]*$/', $int) === 1;
    }

    /**
     * Validation method for department ids
     * @param int $int The integer to validate
     * @return bool True if the integer is valid, false otherwise
     */
    public function validateDepartmentId(int $int): bool
    {
        // Check if the department id is valid (A positive integer)
        return preg_match('/^[1-9][0-9]*$/', $int) === 1;
    }

    /**
     * Validation method for strings
     * @param string $string The string to validate
     * @return bool True if the string is valid, false otherwise
     */
    public function validateString(string $string): bool
    {
        // Check if the string is valid
        // This regex allows for any character, including spaces, and has a length of 1 to 255 characters
        return preg_match('/^.{1,255}$/', $string) === 1;
    }

    /**
     * Validation method for booleans
     * @param bool $boolean The boolean to validate
     * @return bool True if the boolean is valid, false otherwise
     */
    public function validateBoolean(bool $boolean): bool
    {
        // Check if the boolean is valid
        return true;
    }

    /**
     * Validation method for dates
     * @param string $date The date to validate
     * @return bool True if the date is valid, false otherwise
     */
    public function validateDate(string $date): bool
    {
        // Check if the date is valid
        // This regex allows for YYYY-MM-DD format
        return preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) === 1;
    }

    /**
     * Validation method for registration numbers
     * @param string $registration_number The registration number to validate
     * @return bool True if the registration number is valid, false otherwise
     */
    public function validateRegistrationNumber(string $registration_number): bool
    {
        // Check if the registration number is valid
        // This regex allows for 1 to 20 alphanumeric characters
        return preg_match('/^[a-zA-Z0-9]{1,20}$/', $registration_number) === 1;
    }

    /**
     * Get the form identifier
     * @return string The form identifier
     */
    public function getFormIdentifier(): string
    {
        return $this->form_identifier;
    }

    /**
     * Set the form identifier (e.g. "FORM_IDENTIFIER")
     * @notation This should be used to set the form identifier (e.g. "FORM_IDENTIFIER"), this is used to store the form data in the database.
     * @param string $form_identifier The form identifier
     * @throws Exception If the form identifier is not a valid format (e.g. "FORM_IDENTIFIER")
     */
    public function setFormIdentifier(string $form_identifier): void
    {
        // Check if the form identifier is valid (e.g. "FORM_IDENTIFIER")
        if (!preg_match('/^[A-Z_]+$/', $form_identifier)) {
            throw new Exception('The form identifier is not a valid format (e.g. "FORM_IDENTIFIER")');
        }
        $this->form_identifier = $form_identifier;
    }

    /**
     * Get the form name
     * @return string The form name
     */
    public function getFormName(): string
    {
        return $this->form_name;
    }

    /**
     * Set the form name
     * @param string $form_name The form name
     */
    public function setFormName(string $form_name): void
    {
        $this->form_name = $form_name;
    }

    /**
     * Get the form description
     * @return string The form description
     */
    public function getFormDescription(): string
    {
        return $this->form_description;
    }

    /**
     * Set the form description
     * @param string $form_description The form description
     */
    public function setFormDescription(string $form_description): void
    {
        $this->form_description = $form_description;
    }

    /**
     * Get the form as an array
     * @notation This returns the form as an array, including the form identifier, name, description and fields
     * @return array The form as an array
     */
    public function asArray(): array
    {
        return [
            'metadata' => [
                'identifier' => $this->form_identifier,
                'name' => $this->form_name,
                'description' => $this->form_description,
                'submit_button_text' => self::getSubmitButtonText(),
            ],
            'fields' => self::getFormFields(),
        ];
    }

    /**
     * Get the submit button text
     * @return string The submit button text (e.g. "Submit form")
     */
    public function getSubmitButtonText(): string
    {
        return $this->submit_button_text ?? 'Submit form';
    }

    /**
     * Set the submit button text
     * @param string $text The submit button text (e.g. "Submit form")
     */
    public function setSubmitButtonText(string $text): void
    {
        $this->submit_button_text = $text;
    }

    /**
     * Get the form fields
     * @notation This should be used to get the form fields
     * @return array The form fields and their validation methods (E.g. ['name' => 'self::className()::validateString', 'email' => 'self::className()::validateEmail'])
     * @see formRoute - This is used to get the form fields, to dynamically generate the form.
     * @see defineInputFields() - This is used to define the form fields and their validation methods.
     * @see requireInputFields() - This is used to require the input fields to be set.
     */
    public function getFormFields(): array
    {
        function removeMethodPrefix($method): array|string|null
        {
            // Remove the class name and the '::' prefix from the method name
            return preg_replace('/^.*?::/', '', $method);
        }

        // Format the form fields with types, names and values
        $formatted_fields = [];
        foreach ( $this->form_fields_validations as $field => $validation_method ) {
            // Check if the field is valid
            $formatted_fields[$field] = [
                'name' => $field,
                'id' => self::getFormFieldPrefix() . $field,
                'validation' => removeMethodPrefix($validation_method),
                'metadata' => $this->form_fields_metas[$field] ?? null,
            ];
            // Check if the field has options
            if (count(self::getFormFieldOptions($field)) > 0) {
                $formatted_fields[$field]['options'] = self::getFormFieldOptions($field);
            }
        }
        return $formatted_fields;
    }

    /**
     * Get the form field options (if applicable)
     * @notation This should be used to get the form field options (e.g. ['option1' => 'Option 1', 'option2' => 'Option 2'])
     * @param string $field The field to get the options for
     * @return array The form field options
     */
    public function getFormFieldOptions(string $field): array
    {
        // Check if the field is valid
        if (!isset($this->form_fields_options[$field])) {
            return [];
        }
        // Return the form field options
        return $this->form_fields_options[$field];
    }

    /**
     * Set the sanitized data to the form
     * @param array $data The sanitized data
     * @throws Exception If the data is not valid
     */
    public function setSanitizedData(array $data): void
    {
        // Check if the data is valid
        if (empty($data)) {
            throw new Exception('The data is empty');
        }
        // Set the form sanitized data
        $this->form_sanitized_data = $data;
    }

    /**
     * Get department options
     * @return array The department options
     * @notation This should be used to get the department options (e.g. [1 => 'Department 1', 2 => 'Department 2'])
     * @see formRoute - This is used to get the department options, to dynamically generate the form.
     */
    public function getDepartmentOptions(array|null $onlyWithVariableTrue = null): array
    {
        $departments = (new departments_o())->list(false) ?? [];
        $options = [];
        /** @var array $department */
        foreach ( $departments as $department ) {
            // If the department is not visible, skip it
            if (isset($department['visible']) && !$department['visible']) {
                continue;
            }
            // Check if the department has a variable (if the $onlyWithVariableTrue parameter is set)
            if ($onlyWithVariableTrue) {
                $department_variables = (new department_variables_o())->selectDepartment((int)$department['id']);
                // Check if the department has the variables set to true
                foreach ( $onlyWithVariableTrue as $variable ) {
                    //echo 'Checking variable: ' . $variable . ' for department: ' . $department['name'] . PHP_EOL;
                    if (!self::hasPositiveVariable($variable, $department_variables)) {
                        //echo 'Variable: ' . $variable . ' is not set to true for department: ' . $department['name'] . PHP_EOL;
                        continue 2;
                    }
                }
            }
            $options[$department['id']] = $department['name'];
        }
        return $options;
    }

    public function hasPositiveVariable($variable, $department_variables_object): bool
    {
        $positive_values = [
            true,
            'true',
            1,
            '1',
        ];
        return in_array(
            $department_variables_object->getVariable($variable),
            $positive_values);
    }
}