<?php

namespace objects;

use classes\db;
use classes\object_property;
use classes\xlvask;
use Exception;
use helpers\xlvask_customer;
use traits\db_object_t;

class xlvask_customers_o extends db
{
    use db_object_t;

    public object_property $customerId;
    public object_property $name;
    public object_property $vendorId;
    public object_property $customerTypeId;
    public object_property $discount;
    public object_property $phone;
    public object_property $email;
    public object_property $address;
    public object_property $address2;
    public object_property $city;
    public object_property $zip;
    public object_property $userId;
    public object_property $vatnumber;
    public object_property $excludeFromAutoInvoice;
    public object_property $country;
    public object_property $createDate;
    public object_property $externId;
    public object_property $active;
    public object_property $language;
    public object_property $note;
    public object_property $updated;




    public function structure(): void
    {
        $this->setTable('xlvask_customers');
    }

    /**
     * Add a new XL Vask customer
     * @param array $data The properties
     * @returns void
     * @throws Exception If the object was not created successfully
     */
    public function add(array $data): void
    {
        $tmp_id = self::add_object($data);
        $this->id = $tmp_id;
        self::getObjectProperties();
        self::objectChanged();
    }

    public function getObjectProperties(): void
    {
        $this->customerId = new object_property($this->table, $this->id, 'customerId', 'string', false);
        $this->name = new object_property($this->table, $this->id, 'name', 'string', false);
        $this->vendorId = new object_property($this->table, $this->id, 'vendorId', 'string', false);
        $this->customerTypeId = new object_property($this->table, $this->id, 'customerTypeId', 'string', false);
        $this->discount = new object_property($this->table, $this->id, 'discount', 'int', false);
        $this->phone = new object_property($this->table, $this->id, 'phone', 'string', false);
        $this->email = new object_property($this->table, $this->id, 'email', 'string', false);
        $this->address = new object_property($this->table, $this->id, 'address', 'string', false);
        $this->address2 = new object_property($this->table, $this->id, 'address2', 'string', false);
        $this->city = new object_property($this->table, $this->id, 'city', 'string', false);
        $this->zip = new object_property($this->table, $this->id, 'zip', 'string', false);
        $this->userId = new object_property($this->table, $this->id, 'userId', 'string', false);
        $this->vatnumber = new object_property($this->table, $this->id, 'vatnumber', 'string', false);
        $this->excludeFromAutoInvoice = new object_property($this->table, $this->id, 'excludeFromAutoInvoice', 'string', false);
        $this->country = new object_property($this->table, $this->id, 'country', 'string', false);
        $this->createDate = new object_property($this->table, $this->id, 'createDate', 'string', false);
        $this->externId = new object_property($this->table, $this->id, 'externId', 'string', false);
        $this->active = new object_property($this->table, $this->id, 'active', 'string', false);
        $this->language = new object_property($this->table, $this->id, 'language', 'string', false);
        $this->note = new object_property($this->table, $this->id, 'note', 'string', false);
        $this->updated = new object_property($this->table, $this->id, 'updated', 'string', false);
    }

    public function objectChanged(): void
    {
        //TODO: Add cache invalidation
    }

    /**
     * Import the customers from XL Vask
     * @throws Exception If the objects were not successfully added.
     * @returns void
     */
    public function importCustomers(): void
    {
        if (!empty($this->id)) {
            throw new Exception('To prevent issues, having a selected object is not allowed.');
        }
        $customers = $this->getCustomersFromXLVask();
        /** @var string[] $known_customerIds The XL Vask customerIds currently known */
        $known_customerIds = array_map(function ($customer) {
            return $customer['customerId'];
        }, self::getFields(['customerId']));
        /** The XL Vask customers without a matching customerId in the database */
        $new_customers = array_filter($customers, function ($customer) use ($known_customerIds) {
            return !in_array($customer->customerId, $known_customerIds);
        });
        /** The already known customers */
        $known_customers = array_filter($customers, function ($customer) use ($known_customerIds) {
            return in_array($customer->customerId, $known_customerIds);
        });
        unset($known_customerIds);
        /** Adding the new customers */
        foreach ($new_customers as $customer) {
            if (!$customer->isValid()) {
                echo $customer->formattedDetails();
                throw new Exception('A customer from XL Vask is not valid, have the structure changed?');
            }
            // Actually save the customer
            $this->add($customer->toArray());
        }
        unset($new_customers);
        /** Updating the already known customers */
        foreach ($known_customers as $customer) {
            if (!$customer->isValid()) {
                echo $customer->formattedDetails();
                throw new Exception('A customer from XL Vask is not valid, have the structure changed?');
            }
            // Update the existing customer
            $this->updateFieldsWhere($customer->toArray(), ['customerId' => $customer->customerId],1);
            unset($customer); // Free up memory
        }
    }

    /**
     * @return xlvask_customer[]
     * @throws Exception
     */
    public function getCustomersFromXLVask(): array
    {
        /** Get the customers from XL Vask */
        $xlvask = new xlvask();
        $customer_class = $xlvask->new($xlvask->helpers->xlvask_customer);
        /** @var xlvask_customer[] $customers */
        $customers = $customer_class->toObjects($xlvask->getCustomers());
        return $customers;
    }
}