<?php
/**
 * @author Amasty Team
 * @copyright Copyright (c) Amasty (https://www.amasty.com)
 * @package Elastic Search Base for Magento 2
 */

namespace Amasty\ElasticSearch\Model\Search;

use Magento\Framework\Search\RequestInterface;
use Magento\Framework\Search\Response\QueryResponse;
use Amasty\Base\Debug\Log;

class Logger
{
    public const LOG_FILE_NAME_DEFAULT = 'amasty_elastic.log';
    public const LOG_FILE_NAME_BUCKETS = 'amasty_elastic_buckets.log';
    public const LOG_DEPTH_ARRAY = 10;
    public const LOG_DEPTH_OBJECT = 10;

    /**
     * @var \Amasty\ElasticSearch\Model\Config
     */
    private $config;

    /**
     * @var \Amasty\ElasticSearch\Model\Config\Backend\Debug
     */
    private $debugConfig;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $logger;

    public function __construct(
        \Amasty\ElasticSearch\Model\Config $config,
        \Amasty\ElasticSearch\Model\Config\Backend\Debug $debugConfig,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->config = $config;
        $this->debugConfig = $debugConfig;
        $this->logger = $logger;
    }

    /**
     * @param RequestInterface|null $request
     * @param QueryResponse|null $response
     * @param array $rawRequestQuery
     * @param array $rawResponseQuery
     * @return $this
     */
    public function log(
        ?RequestInterface $request = null,
        ?QueryResponse $response = null,
        array $rawRequestQuery = [],
        array $rawResponseQuery = []
    ) {
        if ($this->isLogActive()) {
            Log::setLogFile(self::LOG_FILE_NAME_DEFAULT);
            Log::setArrayDepthLevel(self::LOG_DEPTH_ARRAY);
            Log::setObjectDepthLevel(self::LOG_DEPTH_OBJECT);
            $buckets = $request->getAggregation();
            if (count($buckets) > 1) {
                $this->logRequest($request, $response, $rawRequestQuery, $rawResponseQuery);
            } elseif ($this->logAllRequests()) {
                Log::setLogFile(self::LOG_FILE_NAME_BUCKETS);
                $this->logRequest($request, $response, $rawRequestQuery, $rawResponseQuery);
            }
        }

        return $this;
    }

    /**
     * @param RequestInterface|null $request
     * @param QueryResponse|null $response
     * @param array $rawRequestQuery
     * @param array $rawResponseQuery
     * @return $this
     */
    private function logRequest(
        ?RequestInterface $request = null,
        ?QueryResponse $response = null,
        array $rawRequestQuery = [],
        array $rawResponseQuery = []
    ) {
        if ($this->logRequestObject()) {
            Log::execute(['Request Object' => $request]);
        }

        if ($this->logRawRequest()) {
            Log::execute(['Raw Request' => $rawRequestQuery]);
        }

        if ($this->logRawResponse()) {
            Log::execute(['Raw Response' => $rawResponseQuery]);
        }

        if ($this->logResponseObject()) {
            Log::execute(['Response Object' => $response]);
        }

        return $this;
    }

    /**
     * @return bool
     */
    private function logAllRequests()
    {
        return (bool)$this->config->getDebugConfig('log_buckets_alert_requests');
    }

    /**
     * @return bool
     */
    private function isLogActive()
    {
        if ($value = $this->config->getDebugConfig('use_debug')) {
            return $this->debugConfig->isActive($value);
        }

        return false;
    }

    /**
     * @return bool
     */
    private function logRequestObject()
    {
        return (bool)$this->config->getDebugConfig('log_request_object');
    }

    /**
     * @return bool
     */
    private function logRawRequest()
    {
        return (bool)$this->config->getDebugConfig('log_raw_request');
    }

    /**
     * @return bool
     */
    private function logRawResponse()
    {
        return (bool)$this->config->getDebugConfig('log_raw_response');
    }

    /**
     * @return bool
     */
    private function logResponseObject()
    {
        return (bool)$this->config->getDebugConfig('log_response_object');
    }

    /**
     * @param string $message
     * @param array $context
     * @return void|null
     */
    public function logCritical($message, array $context = [])
    {
        return $this->logger->critical($message, $context);
    }

    /**
     * @param string $message
     * @param array $context
     * @return void|null
     */
    public function logDebug($message, array $context = [])
    {
        return $this->logger->debug($message, $context);
    }

    /**
     * @param string $message
     * @param array $context
     * @return void|null
     */
    public function logError($message, array $context = [])
    {
        return $this->logger->error($message, $context);
    }
}
