<?php

namespace helpers;

use Exception;
use objects\users_o;

class xlvask_customer extends xlvask_helper
{
    protected static array $requiredProperties = [
        'customerId',
        'name',
        'vendorId',
        'customerTypeId',
        'excludeFromAutoInvoice',
        'language',
    ];
    /**
     * The unique identifier for the customer. (UUID format)
     * @var string $customerId
     */
    public string $customerId;
    /**
     * The name of the customer. (Can be null)
     * @var string|null $name
     */
    public ?string $name;
    /**
     * The unique identifier for the vendor associated with the customer. (UUID format)
     * @var string $vendorId
     */
    public string $vendorId = "9dde3a0a-197d-4172-8d0d-b4652d867593"; // For some reason, this is hardcoded in the XLVask system. It has to be this value.
    /**
     * The unique identifier for the customer type. (UUID format)
     * @var string|null $customerTypeId
     * @see xlvask_guid::generate()
     */
    public ?string $customerTypeId = "COMPANY"; // Default to "COMPANY" if not set
    /**
     * The discount percentage for the customer.
     * @var null|integer $discount
     */
    public ?int $discount;
    /**
     * The phone number of the customer. (Can be null)
     * @var string|null $phone
     */
    public ?string $phone;
    /**
     * The email address of the customer. (Can be null)
     * @var string|null $email
     */
    public ?string $email;
    /**
     * The primary address of the customer. (Can be null)
     * @var string|null $address
     */
    public ?string $address;
    /**
     * The secondary address of the customer. (Can be null)
     * @var string|null $address2
     */
    public ?string $address2;
    /**
     * The postal code of the customer's address. (Can be null)
     * @var string|null $zip
     */
    public ?string $zip;
    /**
     * The city of the customer's address. (Can be null)
     * @var string|null $city
     */
    public ?string $city;
    /**
     * The unique identifier for the user associated with the customer. (UUID format)
     * @var string|null $userId
     * @see xlvask_guid::generate()
     */
    public ?string $userId;
    /**
     * The VAT number of the customer. (Can be null)
     * @var null|string $vatnumber
     */
    public ?string $vatnumber;
    /**
     * Indicates whether the customer is excluded from automatic invoicing.
     * @var null|bool $excludeFromAutoInvoice
     */
    public ?bool $excludeFromAutoInvoice;
    /**
     * The country of the customer. (Can be null)
     * @var string|null $country
     */
    public ?string $country;
    /**
     * The date and time when the customer was created. (Can be null)
     * @var string|null $createDate
     */
    public ?string $createDate;
    /**
     * The external identifier for the customer, typically the customer number in the XLVask system.
     * @var string|null $externId
     */
    public ?string $externId;
    /**
     * Indicates whether the customer is active.
     * @var bool|null $active
     */
    public ?bool $active;
    /**
     * The language preference of the customer. (Cannot be null)
     * @var string|null $language
     */
    public ?string $language = 'da'; // Default to 'da' (Danish) if not set.
    /**
     * Additional notes or comments about the customer. (Can be null)
     * @var string|null $note
     */
    public ?string $note;
    /**
     * The date and time when the customer was last updated. (Can be null)
     * @var string|null $updated
     */
    public ?string $updated;

    /**
     * Convert the customer object to an array representation.
     * This method returns an associative array containing all properties of the customer object.
     * @return array
     */
    public function toArray(): array
    {
        return (array)$this;
    }

    /**
     * Get the user associated with this customer.
     * This method retrieves the user object based on the externId of the customer.
     * If the externId is not set or the user cannot be found, it returns null.
     * @return users_o|null
     */
    public function getUser(): ?users_o
    {
        if (empty($this->externId)) {
            return null;
        }
        try {
            $user = new users_o();
            $user->getUserByCustomerNumber((int)$this->externId);
            return $user;
        } catch (Exception $e) {
            // Handle the exception if needed
            return null;
        }
    }

    /**
     * Validate the customer object.
     * This method checks if the customer object has all required properties set.
     * @return bool
     */
    public function isValid(): bool
    {
        // Check if the required properties are set
        foreach ( self::$requiredProperties as $property ) {
            if (!$this->isPropertyValid($property)) {
                // If any required property is not valid, return false
                return false;
            }
        }
        // If all required properties are set, return true
        return true;
    }

    /**
     * Check if a property is valid.
     * This method checks if a given property exists in the customer object and is not empty.
     * @param string $property The name of the property to check.
     * @return bool True if the property exists and is not empty, false otherwise.
     */
    public function isPropertyValid(string $property): bool
    {
        if (!property_exists($this, $property)) {
            return false; // Property does not exist
        }
        return (!empty($this->{$property}) || $this->{$property} === false);
    }

    /**
     * This method returns an array of required properties for the customer object.
     * Each property is checked for its existence and validity.
     * @return array
     */
    public function getMissingRequiredProperties(): array
    {
        $tmp = [];
        foreach ( self::$requiredProperties as $property ) {
            if (!$this->isPropertyValid($property)) {
                $tmp[] = $property; // Add the property to the array if it is not valid
            }
        }
        return $tmp;
    }
}