<?php

declare(strict_types=1);

namespace App\Handlers;

use App\Services\ProductsService;
use App\Services\SettingsService;
use Exception;
use Openguru\OpenCartFramework\Cache\CacheInterface;
use Openguru\OpenCartFramework\Exceptions\EntityNotFoundException;
use Openguru\OpenCartFramework\Http\Request;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

class ProductsHandler
{
    private SettingsService $settings;
    private ProductsService $productsService;
    private LoggerInterface $logger;
    private CacheInterface $cache;

    public function __construct(
        SettingsService $settings,
        ProductsService $productsService,
        LoggerInterface $logger,
        CacheInterface $cache
    ) {
        $this->settings = $settings;
        $this->productsService = $productsService;
        $this->logger = $logger;
        $this->cache = $cache;
    }

    public function index(Request $request): JsonResponse
    {
        $page = (int) $request->json('page', 1);
        $perPage = min((int) $request->json('perPage', 20), 20);
        $maxPages = (int) $request->json('maxPages', 10);
        $search = trim($request->json('search', ''));
        $filters = $request->json('filters');
        $storeId = $this->settings->get('store.oc_store_id', 0);
        $languageId = $this->settings->config()->getApp()->getLanguageId();

        $response = $this->productsService->getProductsResponse(
            compact('page', 'perPage', 'search', 'filters', 'maxPages'),
            $languageId,
            $storeId,
        );

        return new JsonResponse($response);
    }

    public function show(Request $request): JsonResponse
    {
        $productId = (int) $request->get('id');

        try {
            $product = $this->productsService->getProductById($productId);
        } catch (EntityNotFoundException $exception) {
            return new JsonResponse([
                'message' => 'Product with id ' . $productId . ' not found',
            ], Response::HTTP_NOT_FOUND);
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            throw new RuntimeException('Error get product with id ' . $productId, 500);
        }

        return new JsonResponse([
            'data' => $product,
        ]);
    }

    public function getProductImages(Request $request): JsonResponse
    {
        $productId = (int) $request->get('id');

        try {
            $images = $this->productsService->getProductImages($productId);
        } catch (EntityNotFoundException $exception) {
            return new JsonResponse([
                'message' => 'Product with id ' . $productId . ' not found',
            ], Response::HTTP_NOT_FOUND);
        } catch (Exception $exception) {
            $this->logger->error('Could not load images for product ' . $productId, ['exception' => $exception]);
            $images = [];
        }

        return new JsonResponse([
            'data' => $images,
        ]);
    }

    public function getSearchPlaceholder(Request $request): JsonResponse
    {
        $storeId = $this->settings->get('store.oc_store_id', 0);
        $languageId = $this->settings->config()->getApp()->getLanguageId();
        $cacheKey = "products.search_placeholder.{$storeId}.{$languageId}";

        $cached = $this->cache->get($cacheKey);

        if ($cached !== null) {
            return new JsonResponse($cached);
        }

        $response = $this->productsService->getProductsResponse(
            [
                'page' => 1,
                'perPage' => 3,
                'search' => '',
                'filters' => [],
                'maxPages' => 1,
            ],
            $languageId,
            $storeId,
        );

        // Кешируем на 24 часа
        $this->cache->set($cacheKey, $response, 60 * 60 * 24);

        return new JsonResponse($response);
    }
}
