<?php

declare(strict_types=1);

class WebserviceSpecificManagementSearch extends WebserviceSpecificManagementSearchCore
{
    /**
     * @throws WebserviceException
     */
    public function manage(): void
    {
        if (isset($this->wsObject->urlSegment[1]) && 'SearchExportProduct' === $this->wsObject->urlSegment[1]) {
            try {
                if (isset($this->wsObject->urlFragments['searchbyfilters']) && $this->wsObject->urlFragments['searchbyfilters']) {
                    $searchByFilters = $this->wsObject->urlFragments['searchbyfilters'];
                    $data = \json_decode($searchByFilters, true);
                    if (!\is_array($data)) {
                        \http_response_code(400);
                        $response = ['error' => 'bad request'];
                    } else {
                        $response = $this->searchByFilter($data);
                    }
                } elseif (isset($this->wsObject->urlFragments['searchTerm']) && $this->wsObject->urlFragments['searchTerm']) {
                    $response = $this->searchByTerm($this->wsObject->urlFragments['searchTerm']);
                } else {
                    \http_response_code(400);
                    $response = ['error' => 'bad request'];
                }
            } catch (Exception $exception) {
                \http_response_code(500);
                $response = ['error' => $exception->getMessage()];
            }

            \header('Content-Type: application/json');
            echo \json_encode($response);
            exit;
        }
        parent::manage();
    }

    /**
     * This must be return an array with specific values as WebserviceRequest expects.
     *
     * @phpstan-ignore-next-line
     *
     * @return array<mixed>
     */
    public function getContent()
    {
        return $this->objOutput->getObjectRender()->overrideContent($this->output);
    }

    /**
     * @return array<string, mixed>
     *
     * @throws PrestaShopDatabaseException
     */
    private function searchByTerm(string $searchTerm): array
    {
        $db = Db::getInstance();

        $searchTerm = \trim($searchTerm);

        $query = '
        SELECT DISTINCT product.id_product AS id, product_lang.name
        FROM `' . _DB_PREFIX_ . 'product` AS product
        INNER JOIN `' . _DB_PREFIX_ . 'product_lang` as product_lang on product_lang.id_product =  product.id_product
        INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` as product_attribute on product_attribute.id_product =  product.id_product

      WHERE product_lang.name LIKE "%' . $db->escape($searchTerm) . '%"
        OR product_attribute.reference = "' . $db->escape($searchTerm) . '"
        LIMIT 20';

        $result = $db->executeS($query);

        if (!\is_array($result)) {
            $result = [];
        }

        return $result;
    }

    /**
     * @param array<string, string[]> $filters
     *
     * @return array<string, mixed>
     *
     * @throws PrestaShopDatabaseException
     */
    private function searchByFilter(array $filters): array
    {
        $query = '
        SELECT DISTINCT product_lang.id_product AS id, product_lang.name
        FROM `' . _DB_PREFIX_ . 'product` AS product
        INNER JOIN `' . _DB_PREFIX_ . 'product_lang` as product_lang on product_lang.id_product =  product.id_product
        ';

        $queryWhere = [];

        foreach ($filters as $filterValues) {
            if (!empty($filterValues)) {
                // Nettoyage des valeurs
                $cleanFilterValues = \array_map(fn ($value) => (int) $value, $filterValues);

                $queryWhere[] = 'product.id_product IN ('
                    . 'SELECT DISTINCT id_product'
                    . ' FROM ps_feature_product'
                    . ' WHERE id_feature_value IN ('
                    . \implode(',', $cleanFilterValues)
                    . '))';
            }
        }

        $query .= 'WHERE ' . \implode(' AND ', $queryWhere);

        $db = Db::getInstance();

        $result = $db->executeS($query);

        if (!\is_array($result)) {
            $result = [];
        }

        return $result;
    }
}
