<?php

declare(strict_types=1);
/**
 * Created by PhpStorm.
 * User: Julien
 * Date: 28/05/2020
 * Time: 13:02.
 */
class CustomersController
{
    public const MAX_CUSTOMERS_RESULT = 10;

    protected \Clinique $clinique;

    protected \HideString $hideString;

    protected bool $isSuperAdmin;

    public function __construct(Clinique $clinique, HideString $hideString, bool $isSuperAdmin)
    {
        $this->clinique = $clinique;
        $this->hideString = $hideString;
        $this->isSuperAdmin = $isSuperAdmin;
    }

    /**
     * @return mixed[][]
     *
     * @throws PrestaShopDatabaseException
     */
    public function searchCustomerWithfilter(string $filter, string $value): array
    {
        $db = Db::getInstance();

        if ('email' === $filter) {
            $value = '%' . $value . '%';

            $request = 'SELECT ' . _DB_PREFIX_ . 'customer.id_default_group, ' . _DB_PREFIX_ . 'customer.id_customer, ' . _DB_PREFIX_ . 'customer.id_gender, ' . _DB_PREFIX_ . 'customer.firstname, '
                . _DB_PREFIX_ . 'customer.lastname, ' . _DB_PREFIX_ . 'customer.email, ' . _DB_PREFIX_ . 'address.phone, ' . _DB_PREFIX_ . 'address.phone_mobile
                                          FROM ' . _DB_PREFIX_ . 'customer  LEFT JOIN ' . _DB_PREFIX_ . 'address ON ' . _DB_PREFIX_ . 'customer.id_customer = ' . _DB_PREFIX_
                . 'address.id_customer WHERE ' . _DB_PREFIX_ . 'customer.email LIKE "' . $db->escape($value) . '" LIMIT ' . (int) self::MAX_CUSTOMERS_RESULT;
        } elseif ('phone' === $filter) {
            $phoneWithSpace = '%' . wordwrap($value, 2, ' ', true) . '%'; // Ajoute des espaces dans le numéro
            $phonewithoutSpace = '%' . str_replace(' ', '', $value) . '%'; // Retire les espaces dans le numéro

            // Effectue une recherche dans le numéro mobile et fixe avec un numero contenant des espaces ou non

            $request = 'SELECT ' . _DB_PREFIX_ . 'customer.id_default_group, ' . _DB_PREFIX_ . 'customer.id_customer, ' . _DB_PREFIX_ . 'customer.id_gender, ' . _DB_PREFIX_ . 'customer.firstname, '
                . _DB_PREFIX_ . 'customer.lastname,  ' . _DB_PREFIX_ . 'customer.email, ' . _DB_PREFIX_ . 'address.phone, ' . _DB_PREFIX_ . 'address.phone_mobile
                                              FROM ' . _DB_PREFIX_ . 'customer LEFT JOIN ' . _DB_PREFIX_ . 'address ON ' . _DB_PREFIX_ . 'customer.id_customer = ' . _DB_PREFIX_
                . 'address.id_customer WHERE ' . _DB_PREFIX_ . 'address.phone_mobile  LIKE "' . $db->escape($phoneWithSpace) . '" OR ' . _DB_PREFIX_ . 'address.phone_mobile LIKE "' . $db->escape(
                    $phonewithoutSpace
                ) . '" OR ' . _DB_PREFIX_ . 'address.phone  LIKE "' . $db->escape($phoneWithSpace) . '" OR ' . _DB_PREFIX_ . 'address.phone  LIKE "' . $db->escape($phonewithoutSpace) . '" LIMIT '
                . (int) self::MAX_CUSTOMERS_RESULT;
        } elseif ('name' === $filter) {
            $value = '%' . $value . '%';

            $request = 'SELECT ' . _DB_PREFIX_ . 'customer.id_default_group, ' . _DB_PREFIX_ . 'customer.id_customer, ' . _DB_PREFIX_ . 'customer.id_gender, ' . _DB_PREFIX_ . 'customer.firstname, '
                . _DB_PREFIX_ . 'customer.lastname,  ' . _DB_PREFIX_ . 'customer.email, ' . _DB_PREFIX_ . 'address.phone, ' . _DB_PREFIX_ . 'address.phone_mobile
                                              FROM ' . _DB_PREFIX_ . 'customer LEFT JOIN ' . _DB_PREFIX_ . 'address ON ' . _DB_PREFIX_ . 'customer.id_customer = ' . _DB_PREFIX_
                . 'address.id_customer WHERE  ' . _DB_PREFIX_ . 'customer.lastname  LIKE "' . $db->escape($value) . '" LIMIT ' . (int) self::MAX_CUSTOMERS_RESULT;
        } else {
            throw new \Exception('Invalid filter : ' . $filter);
        }
        $customers = $db->executeS($request);
        \assert(\is_array($customers));

        // Si l'employee connecté est un super admin on exécute pas ce bloc qui censure les resultats
        if (!$this->isSuperAdmin) {
            foreach ($customers as $keyCustomer => $customer) {
                // Si le groupe du client n'est pas celui de la clinique, on cache certaines données
                if ($customer['id_default_group'] !== $this->clinique->id_group) {
                    foreach ($customer as $key => $value) {
                        if ('email' === $key && null != $value) {
                            $customers[$keyCustomer]['email'] = $this->hideString->hideEmail($value);
                        } elseif ('phone' === $key && null != $value) {
                            $customers[$keyCustomer]['phone'] = $this->hideString->hidePhoneNumber($value);
                        } elseif ('phone_mobile' === $key && null != $value) {
                            $customers[$keyCustomer]['phone_mobile'] = $this->hideString->hidePhoneNumber($value);
                        } elseif ('firstname' === $key && null != $value) {
                            $customers[$keyCustomer]['firstname'] = $this->hideString->hideStr($value);
                        } elseif ('lastname' === $key && null != $value) {
                            $customers[$keyCustomer]['lastname'] = $this->hideString->hideStr($value);
                        }
                    }
                }
            }
        }

        // Classe les clients par leur id
        $customersByKeyId = [];
        foreach ($customers as $customer) {
            $idCustomer = $customer['id_customer'];
            if (array_key_exists($idCustomer, $customersByKeyId)) {
                $customersByKeyId[$idCustomer][] = $customer;
            } else {
                $customersByKeyId[$idCustomer] = [$customer];
            }
        }

        // Fusion des différents elements (adresses & numéros)
        $customersFormat = [];
        foreach ($customersByKeyId as $customer) {
            $customersFormat[] = $this->formatCustomerForPps($customer);
        }

        return $customersFormat;
    }

    /**
     * @param int $idCustomer
     *
     * @return mixed[]|string[]
     *
     * @throws PrestaShopDatabaseException
     */
    public function getCustomers(int $idCustomer): array
    {
        $db = Db::getInstance();

        $request = 'SELECT ' . _DB_PREFIX_ . 'customer.id_default_group,
            ' . _DB_PREFIX_ . 'customer.id_gender,
            ' . _DB_PREFIX_ . 'customer.firstname,
            ' . _DB_PREFIX_ . 'customer.lastname,
            ' . _DB_PREFIX_ . 'customer.email,
            ' . _DB_PREFIX_ . 'address.phone,
            ' . _DB_PREFIX_ . 'address.phone_mobile,
            ' . _DB_PREFIX_ . 'address.address1,
            ' . _DB_PREFIX_ . 'address.address2,
            ' . _DB_PREFIX_ . 'address.postcode,
            ' . _DB_PREFIX_ . 'address.city,
            ' . _DB_PREFIX_ . 'address.id_country
            FROM ' . _DB_PREFIX_ . 'customer
            LEFT JOIN ' . _DB_PREFIX_ . 'address
                ON ' . _DB_PREFIX_ . 'customer.id_customer = ' . _DB_PREFIX_ . 'address.id_customer
            WHERE
                ' . _DB_PREFIX_ . 'customer.id_customer = "' . $idCustomer . '"';

        $customer = $db->executeS($request);
        \assert(\is_array($customer));

        $customerFormat = $this->formatCustomerForPps($customer);
        $responseContent = $customerFormat;

        // Si l'employee connecté est un super admin, on n'exécute pas ce bloc qui censure les resultats
        if (
            !$this->isSuperAdmin
            && $customerFormat['id_default_group'] !== $this->clinique->id_group
        ) {
            \header('HTTP/1.0 401 Unauthorized');
            $responseContent = ['error' => 'Unauthorized'];
        }

        return $responseContent;
    }

    /**
     * Fusionne les différents elements des clients en un seul tableau (numéros & adresses)
     *
     * @param array<string, string|int>[] $datasCustomer
     *
     * @return array<mixed>
     */
    protected function formatCustomerForPps(array $datasCustomer): array
    {
        $phone = [];
        $phoneMobile = [];
        $addresses = [];

        foreach ($datasCustomer as $data) {
            if (null != $data['phone']) {
                $phoneMobile[] = $data['phone'];
            }

            if (null != $data['phone_mobile']) {
                $phoneMobile[] = $data['phone_mobile'];
            }

            if (isset($data['address1'])) {
                $address = [
                    'address1' => $data['address1'],
                    'address2' => $data['address2'],
                    'postcode' => $data['postcode'],
                    'city' => $data['city'],
                    'id_country' => $data['id_country'],
                ];
                $addresses[] = $address;
            }
        }

        $datasCustomer[0]['phone'] = $phone;
        $datasCustomer[0]['phone_mobile'] = $phoneMobile;

        if (!empty($addresses)) {
            unset($datasCustomer[0]['address1']);
            unset($datasCustomer[0]['address2']);
            unset($datasCustomer[0]['postcode']);
            unset($datasCustomer[0]['city']);
            unset($datasCustomer[0]['id_country']);
            $datasCustomer[0]['addresses'] = $addresses;
        }

        return $datasCustomer[0];
    }

    /**
     * @return string[]
     */
    public function getLastOrders(int $idCustomer, int $maxOrder = 10): array
    {
        $customer = new Customer($idCustomer);

        if (!$customer->id) {
            \header('HTTP/1.0 404 Bad Request');

            return ['error' => 'Bad Request'];
        }

        // Vérification super admin ou client appartient à la clinique
        if (true === $this->isSuperAdmin || $customer->id_default_group == $this->clinique->id_group) {
            $db = Db::getInstance();
            $request = 'SELECT
                ' . _DB_PREFIX_ . 'orders.id_order,
                ' . _DB_PREFIX_ . 'orders.reference,
                ' . _DB_PREFIX_ . 'orders.total_paid_real as price,
                ' . _DB_PREFIX_ . 'orders.invoice_date as date,
                ' . _DB_PREFIX_ . 'orders.id_cart
                FROM ' . _DB_PREFIX_ . 'orders
                WHERE ' . _DB_PREFIX_ . 'orders.id_customer = "' . $idCustomer . '"
                AND ' . _DB_PREFIX_ . 'orders.valid = 1
                ORDER BY ' . _DB_PREFIX_ . 'orders.invoice_date DESC
                LIMIT ' . $maxOrder;
            $orders = $db->executeS($request);
            \assert(\is_array($orders));

            foreach ($orders as $index => $order) {
                $idOrder = $order['id_order'];
                $order = new Order($idOrder);

                $orderDetail = $order->getOrderDetailList();
                $products = [];

                foreach ($orderDetail as $product) {
                    $link = new Link();
                    $url = $link->getProductLink(new Product($product['product_id']));

                    $productDetails = [
                        'id_product' => $product['product_id'],
                        'quantity' => $product['product_quantity'],
                        'name' => $product['product_name'],
                        'url' => $url,
                    ];

                    $products[] = $productDetails;
                }

                $orders[$index]['products'] = $products;
            }

            return $orders;
        } else {
            \header('HTTP/1.0 401 Unauthorized');

            return ['error' => 'Unauthorized'];
        }
    }
}
