<?php

/**
 * Receipt Article model.
 *
 * @package northmill-online-shared
 */
declare (strict_types=1);
namespace Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Models\Receipts;

use JsonSerializable;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Helpers\General_Helpers;
/**
 * Class Article_Model
 */
class Receipt_Article_Model implements JsonSerializable
{
    /**
     * If this article is for a receipt, this is the index of the order in the Order property in the receipt.
     * As of writing this, we only ever have one order per receipt,
     * so this is always 0, or null if article is not for a receipt.
     *
     * @var int|null
     */
    protected ?int $OrderIndex;
    /**
     * Article SKU
     *
     * @var string
     */
    protected string $ArticleNumber;
    /**
     * Article name.
     *
     * @var string
     */
    protected string $Name;
    /**
     * Number of this article in the order.
     * Negative for refunds.
     *
     * @var float
     */
    protected float $Quantity;
    /**
     * Single article price including VAT.
     *
     * @var string
     */
    protected string $UnitPrice;
    /**
     * Single article price including VAT, but without discounts.
     *
     * @var string
     */
    protected string $UnitPriceWithoutDiscounts;
    /**
     * VAT rate in percent.
     *
     * @var float
     */
    protected float $VatRate;
    /**
     * Line total price including VAT.
     *
     * @var string
     */
    protected string $TotalPriceIncVat;
    /**
     * Line total price excluding VAT.
     *
     * @var string
     */
    protected string $TotalPriceExVat;
    /**
     * Line total VAT.
     *
     * @var string
     */
    protected string $TotalVat;
    /**
     * Bookkeeping account number for this article.
     *
     * @var int|null
     */
    protected ?int $BookkeepingAccount;
    /**
     * Discounts for this article.
     *
     * @var Receipt_Discount_Model[]
     */
    protected array $Discounts;
    /**
     * Article attributes.
     * This is an array of key-value pairs.
     * Keys:
     *  AttrbuteType (misspelled in API) – string (example: "SerialNumber")
     *  Value – attribute value (example: "123456")
     *
     * @var array
     */
    protected array $Attributes;
    /**
     * Taxes totals.
     *
     * @var array|null
     */
    protected ?array $taxes_totals;
    /**
     * Type of the article.
     *
     * @var string
     */
    protected string $type;
    /**
     * Constructor method for the class. Sets the properties of the object one by one.
     */
    public function __construct(?int $order_index = null, string $article_number = '', string $name = '', float $quantity = 0, float|string $unit_price = 0.0, float|string $unit_price_without_discounts = 0.0, float $vat_rate = 0, float|string $total_price_including_vat = 0.0, float|string $total_price_excluding_vat = 0.0, float|string $total_vat = 0.0, ?int $bookkeeping_account = null, string $type = '', array $taxes_totals = array(), array $discounts = array(), array $attributes = array())
    {
        $this->OrderIndex = $order_index;
        $this->ArticleNumber = $article_number;
        $this->Name = $name;
        $this->Quantity = $quantity;
        $this->UnitPrice = General_Helpers::round_and_format_number($unit_price);
        $this->UnitPriceWithoutDiscounts = General_Helpers::round_and_format_number($unit_price_without_discounts);
        $this->VatRate = $vat_rate;
        $this->TotalPriceIncVat = General_Helpers::round_and_format_number($total_price_including_vat);
        $this->TotalPriceExVat = General_Helpers::round_and_format_number($total_price_excluding_vat);
        $this->TotalVat = General_Helpers::round_and_format_number($total_vat);
        $this->BookkeepingAccount = $bookkeeping_account;
        $this->Discounts = $discounts;
        $this->Attributes = $attributes;
        $this->type = $type;
        $this->set_taxes_totals($taxes_totals);
    }
    /**
     * Sets taxes totals with rounded values.
     *
     * @param array $taxes_totals Taxes totals.
     */
    private function set_taxes_totals(array $taxes_totals): void
    {
        // Round each tax item.
        foreach ($taxes_totals as $key => $tax) {
            foreach ($tax as $tax_key => $tax_value) {
                $taxes_totals[$key][$tax_key] = General_Helpers::round_and_format_number($tax_value);
            }
        }
        $this->taxes_totals = $taxes_totals;
    }
    /**
     * Gets total tax for specific rate.
     *
     * @param int $rate_id Rate ID.
     *
     * @return float|null Total tax on success, else null.
     */
    public function get_tax_total(int $rate_id): ?float
    {
        if (isset($this->taxes_totals['total'][$rate_id])) {
            return (float) $this->taxes_totals['total'][$rate_id];
        }
        return null;
    }
    /**
     * @return string
     */
    public function get_total_price_inc_vat(): string
    {
        return $this->TotalPriceIncVat;
    }
    /**
     * @return string
     */
    public function get_total_price_ex_vat(): string
    {
        return $this->TotalPriceExVat;
    }
    /**
     * @return int|null
     */
    public function get_bookkeeping_account(): ?int
    {
        return $this->BookkeepingAccount;
    }
    /**
     * @return string
     */
    public function get_type(): string
    {
        return $this->type;
    }
    /**
     * @return string
     */
    public function get_sku(): string
    {
        return $this->ArticleNumber;
    }
    /**
     * @return string
     */
    public function get_name(): string
    {
        return $this->Name;
    }
    /**
     * Get article quantity.
     *
     * @return float
     *
     * @used Northmill Sync
     */
    public function get_quantity(): float
    {
        return $this->Quantity;
    }
    /**
     * Get the total price not accounting for discounts.
     *
     * @return string
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_unit_price_without_discounts(): string
    {
        return $this->UnitPriceWithoutDiscounts;
    }
    /**
     * Get the VAT rate for this article.
     *
     * @return float
     * @noinspection PhpUnused Used by plugins loading this composer package.
     */
    public function get_vat_rate(): float
    {
        return $this->VatRate;
    }
    /**
     * Get the total discount for this article.
     *
     * @return float Discount as a float. Must be rounded before use.
     */
    public function get_total_discount(): float
    {
        return array_reduce($this->Discounts, function ($carry, $discount) {
            /**
             * Current discount.
             *
             * @var Receipt_Discount_Model $discount
             */
            if ('amount' === strtolower($discount->get_type())) {
                return $carry + floatval($discount->get_amount());
            }
            return 0.0;
        }, 0.0);
    }
    /**
     * Get item for JSON serialization.
     *
     * @return array
     */
    public function jsonSerialize(): array
    {
        return array('OrderIndex' => $this->OrderIndex, 'ArticleNumber' => $this->ArticleNumber, 'Name' => $this->Name, 'Quantity' => $this->Quantity, 'UnitPrice' => $this->UnitPrice, 'VatRate' => $this->VatRate, 'TotalPriceIncVat' => $this->TotalPriceIncVat, 'TotalPriceExVat' => $this->TotalPriceExVat, 'TotalVat' => $this->TotalVat, 'Discounts' => $this->Discounts, 'Attributes' => $this->Attributes);
    }
}
