<?php

namespace objects;

use classes\db;
use classes\object_property;
use Exception;
use traits\db_object_t;

class customer_default_department_o extends db
{
    use db_object_t;

    public object_property $customer_number; // The customer number (E-conomic)
    public object_property $department; // The department ID
    public object_property $created_at; // The timestamp of when the record was created
    public object_property $updated_at; // The timestamp of when the record was updated

    /**
     * Convert the object to an array
     * @return array
     * @throws Exception If the object is not selected
     */
    public function asArray(): array
    {
        self::requireSelected();
        return [
            'id' => (int)$this->id,
            'customer_number' => (int)$this->customer_number->value(),
            'department' => (int)$this->department->value(),
            'created_at' => (string)$this->created_at->value(),
            'updated_at' => (string)$this->updated_at->value(),
        ];
    }


    /**
     * @throws Exception If the creation of the object fails
     */
    public function add(int $customer_number, int $department): void
    {
        global $db, $response;
        $tmp_id = self::add_object([
            'customer_number' => (int)$customer_number,
            'department' => (int)$department,
        ]);
        self::select((int)$tmp_id);
        self::objectChanged();
    }

    public function objectChanged(): void
    {
        // Since the customer_vehicles object is not cached, there is no need to invalidate the cache
    }

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

    public function getObjectProperties(): void
    {
        $this->customer_number = new object_property($this->table, $this->id, 'customer_number', 'int', true);
        $this->department = new object_property($this->table, $this->id, 'department', 'int', true);
        $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', true);
        $this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', true);
    }

    /**
     * Get the default department for a customer by customer number
     * @param int $customer_number
     * @return int|null Returns the department ID if it exists, null otherwise.
     * @throws Exception If the user does not have a default department set.
     */
    public function getDefaultDepartment(int $customer_number): int|null
    {
        if (!$this->doesUserHaveDefaultDepartment($customer_number)) {
            return null;
        }
        $this->selectByCustomerNumber($customer_number);
        if ($this->exists()) {
            return (int)$this->department->value();
        } else {
            return null;
        }
    }

    /**
     * Check if the user has a default department set
     * @param int $customer_number
     * @return bool Returns true if the user has a default department set, false otherwise.
     */
    public function doesUserHaveDefaultDepartment(int $customer_number): bool
    {
        return $this->getIdByCustomerNumber($customer_number) !== null;
    }

    /**
     * Get the ID of the customer_default_department object by customer number
     * @param int $customer_number
     * @return int|null Returns the ID of the customer_default_department object, if it exists. Returns null, if it does not exist.
     */
    public function getIdByCustomerNumber(int $customer_number): ?int
    {
        $matches = self::getFieldsWhere([
            'customer_number' => (int)$customer_number,
        ], [
            'id'
        ]);
        if (count($matches) > 0) {
            // There is a match, so return the ID
            return (int)$matches[0]['id'];
        } else {
            // There's no match, so return null
            return null;
        }
    }

    /**
     * Get the customer_default_department object by customer number
     * @param int $customer_number
     * @return customer_default_department_o|null Returns the customer_default_department_o object if it exists, null otherwise.
     * @throws Exception If the user does not have a default department set.
     * @see doesUserHaveDefaultDepartment()
     * @see getIdByCustomerNumber()
     */
    public function selectByCustomerNumber(int $customer_number): ?customer_default_department_o
    {
        $this->select($this->getIdByCustomerNumber($customer_number));
        if ($this->exists()) {
            return $this;
        } else {
            throw new Exception('Unable to select customer default department object for customer number: ' . $customer_number);
        }
    }
}