<?php

namespace helpers;

use classes\economic;
use Exception;

class economic_customer
{
    /**
     * The Economic customerNumber, which is the unique identifier for a customer
     * @var int $customer_number
     */
    protected int $customer_number;
    /**
     * The raw customer data from the Economic API
     * @var object $customer_data
     */
    protected object $customer_data_object;


    /**
     * Construct a new Economic customer object
     * @throws Exception if the customer does not exist
     */
    public function __construct(int $customer_number)
    {
        self::setCustomerNumber($customer_number);
        self::requireExists();
        self::fetchCustomerData();
        self::requireSelected();
    }

    /**
     * Check if a customer exists
     * @param int $customer_number The Economic customer number to check for
     * @throws Exception if the customer does not exist
     */
    protected function requireExists(): void
    {
        if (!self::exists()) {
            throw new Exception('The customer does not exist in the Economic system');
        }
    }

    /**
     * Check if a customer exists in the Economic system
     * @return bool True if the customer exists, false if not
     * @throws Exception
     */
    public function exists(): bool
    {
        // Make sure the customer number is set
        self::requireCustomerNumber();
        // Check if the customer exists
        $economic = new economic();
        return $economic->customers->customers->exists(self::getCustomerNumber());
    }

    /**
     * Require that the customer number is set
     * @throws Exception if the customer number is not set
     */
    protected function requireCustomerNumber(): void
    {
        if (!isset($this->customer_number)) {
            throw new Exception('The customer number is not set');
        }
    }

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

    /**
     * Set the customer number
     * @param int $customer_number The Economic customer number
     */
    protected function setCustomerNumber(int $customer_number): void
    {

        $this->customer_number = $customer_number;
    }

    /**
     * Fetch the customer data from the Economic API and store it in the object property $customer_data_object
     * @throws Exception if the customer data could not be fetched
     * @throws Exception if the customer data is invalid or empty
     */
    protected function fetchCustomerData(): void
    {
        // Get the customer data from the Economic API
        $economic = new economic();
        $tmp = $economic->customers->customers->get($this->customer_number);
        // Check if the customer data is invalid or empty
        if (!isset($tmp->customerNumber)) {
            throw new Exception('The customer data is invalid or empty');
        }
        // Store the customer data in the object property
        $this->customer_data_object = $tmp;
    }

    /**
     * Require that a customer is selected, i.e. that the customer data is valid and not empty
     * @throws Exception if the customer data is invalid or empty
     */
    protected function requireSelected(): void
    {
        if (!isset($this->customer_data_object->customerNumber)) {
            throw new Exception('The customer data is invalid or empty');
        }
    }

    /**
     * Get the customer data as an object
     * @return object The customer data as an object
     * @throws Exception if the customer data is invalid or empty
     */
    public function asObject(): object
    {
        self::requireSelected();
        return $this->customer_data_object;
    }

    /**
     * Get the customer name
     * @return string The customer name
     * @throws Exception if the customer data is invalid or empty
     */
    public function getName(): string
    {
        self::requireSelected();
        return $this->customer_data_object->name;
    }

    /**
     * Get the customer email
     * @return string The customer email
     * @throws Exception if the customer data is invalid or empty
     */
    public function getEmail(): string
    {
        self::requireSelected();
        return $this->customer_data_object->email;
    }

    /**
     * Get the customer address
     * @return string The customer address
     * @throws Exception if the customer data is invalid or empty
     */
    public function getAddress(): string
    {
        self::requireSelected();
        // Check if the address is set
        return ($this->customer_data_object->address ?? 'Ingen addresse');
    }

    /**
     * Get the customer postal code
     * @return string The customer postal code
     * @throws Exception if the customer data is invalid or empty
     */
    public function getZipCode(): string
    {
        self::requireSelected();
        return $this->customer_data_object->zip ?? '0000';
    }

    /**
     * Get the customer city
     * @return string The customer city
     * @throws Exception if the customer data is invalid or empty
     */
    public function getCity(): string
    {
        self::requireSelected();
        return $this->customer_data_object->city ?? 'Ukendt';
    }

    /**
     * Get the customer country
     * @return string The customer country
     * @throws Exception if the customer data is invalid or empty
     */
    public function getCountry(): string
    {
        self::requireSelected();
        return $this->customer_data_object->country ?? 'Ukendt';
    }

    /**
     * Get the customers payment terms number
     * @return int The customers payment terms number
     * @throws Exception if the customer data is invalid or empty
     */
    public function getPaymentTermsNumber(): int
    {
        self::requireSelected();
        return $this->customer_data_object->paymentTerms->paymentTermsNumber;
    }

    /**
     * Get the customers currency (ISO 4217 code, e.g. DKK)
     * @return string The customers currency
     * @throws Exception
     */
    public function getCurrency(): string
    {
        self::requireSelected();
        return $this->customer_data_object->currency ?? 'DKK';
    }

    /**
     * Get the customers VAT zone number
     * @return int The customers VAT zone number
     * @throws Exception if the customer data is invalid or empty
     */
    public function getVatZoneNumber(): int
    {
        self::requireSelected();
        return $this->customer_data_object->vatZone->vatZoneNumber;
    }

}