<?php

namespace customers;

use economic_m;
use Exception;
use objects\users_o;

class economicCustomers extends economic_m
{
    public users_o $users_o;

    public function searchCustomers(string|int $search, string $filter, int $limit = 10, int $page = 1): object
    {
        // Make sure the search string is ready for the API
        $search = urlencode($search);
        // Search for customers
        $url = '/customers?filter=' . $filter . '$like:' . $search . '&pagesize=' . $limit . '&skippages=' . $page - 1;
        $response = $this->send_request($url, 'GET', '');
        return json_decode($response);
    }

    public function getCustomerName(int $customer_number): string|null
    {
        // Check if the customer name is cached
        $tmp_user = self::getUsersObject()->getUserByCustomerNumber($customer_number);
        $cached = $tmp_user->getCached('economic_customer');
        if ($cached) {
            return $cached->name;
        }
        // Get the customer name from the economic system
        $tmp_user->getCustomerEcocomicData($customer_number);
        $cached = $tmp_user->getCached('economic_customer');
        if ($cached) {
            return $cached->name;
        }
        return null;
    }

    public function getUsersObject(): users_o
    {
        if (!isset($this->users_o)) {
            $this->users_o = new users_o();
        }
        return $this->users_o;
    }

    public function getCustomerId(int $customerNumber): object|bool
    {
        // Check if the customer exists
        $url = '/customers/' . $customerNumber;
        $response = $this->send_request($url, 'GET', '');
        $response = json_decode($response);

        return isset($response->customerNumber) ? $response : false;
    }

    public function getCustomerProduct(int $customer_number, int $product_id): object
    {
        // Get the customer product
        $url = '/customers/' . $customer_number . '/templates/invoiceline/' . $product_id;
        $response = $this->send_request($url, 'GET', '');
        return json_decode($response);
    }

    public function getCustomerDiscountPercentage(int $customer_number): int
    {
        // If the customer number is 0, return 0
        if ($customer_number === 0) {
            return 0;
        }
        // Get the customer products
        $products = $this->getCustomerProducts($customer_number, 1)->collection;
        $discount = $this->getCustomerProductDiscount($customer_number, $products[0]->product->productNumber);
        // Since the discount is global, we only need to get the discount for one product
        return $discount->discountPercentage ?? 0;
    }

    public function getCustomerProducts(int $customer_number, int $limit = 10, int $page = 1): object
    {
        // Get the customer products
        $url = '/customers/' . $customer_number . '/templates/invoiceline/?pagesize=' . $limit . '&skippages=' . $page - 1;
        $response = $this->send_request($url, 'GET', '');
        return json_decode($response);
    }

    public function getCustomerProductDiscount(int $customer_number, int $product_id)
    {
        // Get the customer global discount
        $url = '/customers/' . $customer_number . '/templates/invoiceline/' . $product_id;
        $response = $this->send_request($url, 'GET', '');
        $response = json_decode($response);
        return $response;
    }

    /**
     * Get the list of customers
     * @param int $page
     * @param int $limit
     * @param string|null $search
     * @return object The list of customers
     * @throws Exception
     */
    public function listCustomers(int $page, int $limit, string|null $search = null): object
    {
        // Normalize pagination parameters
        $page = max(1, $page); // Ensure it's at least 1
        $skipPages = $page - 1;

        // Construct the base URL with pagination
        $url = '/customers?pagesize=' . $limit . '&skippages=' . $skipPages;

        // Define filterable property groups
        $likeSupported = [
            'zip', 'customerNumber', 'customerGroup.customerGroupNumber', 'name', 'address',
            'city', 'country', 'email', 'telephoneAndFaxNumber', 'website', 'mobilePhone', 'corporateIdentificationNumber'
        ];

        // If a search term is present, build the filter expressions
        if (!empty($search)) {
            // Escape special characters in the search string
            $escapedSearch = str_replace(
                ['$', '(', ')', '*', ',', '[', ']'],
                ['$$', '$(', '$)', '$*', '$,', '$[', '$]'],
                $search
            );

            // Build $like filters
            $filters = [];
            foreach ( $likeSupported as $property ) {
                $filters[] = $property . '$like:' . $escapedSearch;
            }

            // Join the filters with `$or:`
            $filterString = implode('$or:', $filters);

            // URL encode and append the filter string
            $url .= '&filter=' . urlencode($filterString);
        }

        // Send the GET request to the API endpoint
        $response = $this->send_request($url, 'GET', '');

        // Validate and decode the response safely
        $responseObject = json_decode($response);
        if ($responseObject === null) {
            throw new Exception('Failed to decode the response from the API');
        }
        return $responseObject;
    }


}