<?php

namespace endpoints\orders;

use classes\economic;
use Exception;
use objects\orders_o;
use objects\products_o;
use traits\economic_endpoint_t;

class economic_invoices_draft_endpoint
{
    use economic_endpoint_t;

    /**
     * Get draft invoice
     * @param int $invoice_id Invoice id to get
     * @return object {invoice}
     * @throws Exception If the request fails
     */
    public function get(int $invoice_id): object
    {
        $response = $this->send_request(
            '/invoices/drafts/' . $invoice_id,
            'GET'
        );
        // Return the response as an object
        return json_decode($response);
    }


    /**
     * Get draft invoice from external id
     * @param string $external_id External id to get
     * @return int Invoice id
     * @throws Exception If the request fails
     * @throws Exception If the invoice is not found
     */
    public function get_from_external_id(string $external_id): int
    {
        $response = $this->send_request(
            '/invoices/drafts?filter=references.other$eq:' . $external_id,
            'GET'
        );
        // Return the response as an object
        $response = json_decode($response);
        //var_dump($response);
        if (isset($response->collection[0])) {
            return $response->collection[0]->draftInvoiceNumber;
        } else {
            throw new Exception('Invoice draft with external id (' . $external_id . ') not found');
        }
    }

    /**
     * Add an order to a draft invoice
     * @param int $invoiceDraftId The invoice draft id to add the order to
     * @param orders_o $order The order to add
     * @param string $currency The currency to use (default: DKK)
     * @return void
     * @throws Exception If the request fails
     */
    public function add_order(int $invoiceDraftId, orders_o $order, string $currency = 'DKK'): void
    {
        $draftInvoice = (new economic())->getInvoiceDraft($invoiceDraftId, strtoupper($currency), true);
        // Check if the order includes any items that should be included in the invoice
        if ($order->getIncludeInInvoiceCount() > 0) {
            // Add the transaction header (Timestamp, department, etc.)
            $draftInvoice->addNewTransactionHeader($order);
            // Add the order lines
            $draftInvoice->addOrderItemLines($order);
            // Add an empty line, so the invoice is not empty
            $draftInvoice->addTextLine('');
            // Save the draft invoice lines
            $draftInvoice->addLines();
        }
    }

    /**
     * Add lines to a draft invoice
     * @param int $draft_invoice_number The draft invoice number
     * @param array $draft_lines The draft lines to add
     * @return object {draftInvoiceNumber: number, lines: [invoice_line]}
     * @throws Exception
     */
    public function add_lines(int $draft_invoice_number, array $draft_lines): object
    {
        $response = $this->send_request(
            '/invoices/drafts/' . $draft_invoice_number . '/lines',
            'POST',
            json_encode(
                ['lines' => $draft_lines]
            )
        );
        // Check for errors
        $decoded = json_decode($response);
        if (isset($decoded->errorCode)) {
            $errorMessages = [];
            if (isset($decoded->errors->lines->items) && is_array($decoded->errors->lines->items)) {
                foreach ( $decoded->errors->lines->items as $item ) {
                    if (isset($item->departmentalDistribution->errors) && is_array($item->departmentalDistribution->errors)) {
                        foreach ( $item->departmentalDistribution->errors as $error ) {
                            $errorMessages[] = 'Line ' . $item->arrayIndex . ': ' . $error->errorMessage;
                        }
                    }
                }
            }
            throw new Exception('Error adding lines to draft invoice: ' . implode('; ', $errorMessages) . ')');
        }
        return $decoded;
    }

    /**
     * @throws Exception If the request fails
     */
    public function add_environmental_and_oil_fees(int $draft_id, int $total_amount_invoice, string $currency): void
    {
        // Get the total amount of the invoice
        $draft_invoice = (new economic())->getInvoiceDraft($draft_id, strtoupper($currency), true);
        $total_amount = $total_amount_invoice; // Use the provided total amount
        // Define the products:
        $oil_fee_product_id = 70; // Oil fee product ID
        $environmental_fee_product_id = 71; // Environmental fee product ID
        // Get the percentage rates (price of the products)
        $product_environmental_fee = (new products_o())->select($environmental_fee_product_id);
        $product_oil_fee = (new products_o())->select($oil_fee_product_id);
        // Calculate the fees
        $environmental_fee = (float)round(($total_amount / 100) * (int)$product_environmental_fee->price->value());
        $oil_fee = round(($total_amount / 100) * (int)$product_oil_fee->price->value());
        // Add an extra space before the fees
        //$draft_invoice->addTextLine('');
        // Add the fees to the invoice if they are greater than 0
        if ($environmental_fee > 0) {
            $draft_invoice->addProductLine(
                $product_environmental_fee->economic_product_id->value(),
                $product_environmental_fee->name->value(),
                1,
                $environmental_fee,
                10, // TODO: Make this dynamic
                1, // TODO: Make this dynamic
            );
            $draft_invoice->addProductLine(
                $product_oil_fee->economic_product_id->value(),
                $product_oil_fee->name->value(),
                1,
                $oil_fee,
                10, // TODO: Make this dynamic
                1, // TODO: Make this dynamic
            );
            // Save the draft invoice lines
            $draft_invoice->addLines();
        }
    }
}