<?php

namespace KupShop\IncomakerBundle\Util;

use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\IncomakerBundle\Exceptions\IncomakerSynchronizationException;
use KupShop\IncomakerBundle\IncomakerBundle;
use KupShop\KupShopBundle\Context\CountryContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Util\Compat\SymfonyBridge;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Logging\CustomDataExceptionInterface;
use KupShop\KupShopBundle\Util\System\AsyncQueue;

class IncomakerUtil
{
    protected AsyncQueue $queue;

    /** @required  */
    public function setQueue(AsyncQueue $queue)
    {
        $this->queue = $queue;
    }

    public function addUser(\User $user, $newsletter)
    {
        $api_key = \Settings::getDefault()['incomaker']['api_key'] ?? null;
        if (empty($api_key)) {
            return false;
        }

        $url = findModule(\Modules::INCOMAKER, 'url') ?? 'https://api.incomaker.com';
        $url .= '/commons/v3/contact/'.$api_key;

        $request = SymfonyBridge::getCurrentRequest();
        $permId = $request?->cookies?->get('incomaker_p');
        $data = [
            'clientContactId' => $user->id,
            'email' => $user->email,
            'firstName' => $user->name,
            'lastName' => $user->surname,
            'country' => $user->country ?? Contexts::get(CountryContext::class)->getActiveId(),
            'language' => $user->id_language ?? Contexts::get(LanguageContext::class)->getActiveId(),
            'permId' => $permId,
        ];
        $data = array_filter($data);

        $params = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_HTTPHEADER => ['content-type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_TIMEOUT => 10,
        ];
        $this->queue->addHandler(fn () => $this->curlExec($params), 'Incomaker - přidání nového uživatele', $this->getErrorHandler());

        if ($user->isRegistered()) {
            // send event - register
            $data = ['name' => 'register', 'contact' => ['clientContactId' => $user['id']]];
            if ($permId) {
                $data['permId'] = $permId;
            }
            $this->sendEvent($data);
        }
    }

    public function updateUser(\User $user, $newsletter)
    {
        if (in_array($newsletter, ['Y', 'N'])) {
            $segments = ($newsletter == 'Y' ? ['add' => ['NEWSLETTER']] : ['remove' => ['NEWSLETTER']]);
            $segments = json_encode($segments);
        } else {
            return false;
        }

        $api_key = \Settings::getDefault()['incomaker']['api_key'] ?? null;
        if (empty($api_key)) {
            return false;
        }

        $url = findModule(\Modules::INCOMAKER, 'url') ?? 'https://api.incomaker.com';
        $url .= '/commons/v3/contact/updateSegments/'.$api_key;
        $url .= '?clientContactId='.$user['id'];

        $params = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_HTTPHEADER => ['content-type: application/json'],
            CURLOPT_POSTFIELDS => $segments,
            CURLOPT_TIMEOUT => 10,
        ];
        $this->queue->addHandler(fn () => $this->curlExec($params), 'Incomaker - aktualizace segmentu NEWSLETTER', $this->getErrorHandler());

        // send event - subscribe or unsubscribe (formerly known as churn)
        $request = SymfonyBridge::getCurrentRequest();
        $permId = $request?->cookies?->get('incomaker_p');
        $name = ($newsletter == 'Y' ? 'subscribe' : 'unsubscribe');
        $data = ['name' => $name, 'permId' => $permId, 'contact' => ['clientContactId' => $user['id']]];
        $this->sendEvent($data);

        return true;
    }

    public function sendEvent($data)
    {
        $api_key = \Settings::getDefault()['incomaker']['api_key'];

        $url = findModule(\Modules::INCOMAKER, 'url') ?? 'https://api.incomaker.com';
        $url .= '/commons/v3/event/'.$api_key;

        $params = [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_HTTPHEADER => ['content-type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_TIMEOUT => 10,
        ];
        $this->queue->addHandler(fn () => $this->curlExec($params), "Incomaker - událost '{$data['name']}'", $this->getErrorHandler());
    }

    public function curlExec($params)
    {
        $curl = curl_init();
        curl_setopt_array($curl, $params);

        $response = curl_exec($curl);
        $error = curl_error($curl);
        curl_close($curl);

        $message = '';
        if ($errno = curl_errno($curl)) {
            $message = curl_strerror($errno);
        }

        if ($error) {
            $primary_ip = curl_getinfo($curl, CURLINFO_PRIMARY_IP);
            throw new IncomakerSynchronizationException($error,
                ['params' => $params, 'response' => $response, 'message' => $message, 'primary_ip' => $primary_ip]);
        }

        return $response;
    }

    private function getErrorHandler(): callable
    {
        // custom error handler async queue zprav pro Incomaker
        // chci to do activity logu jako warning, ne jako error
        return function (string $name, \Throwable $e) {
            $message = "Chyba při zpracování asynchronní úlohy: {$name}";
            $data = $e instanceof CustomDataExceptionInterface ? $e->getData() : [];

            addActivityLog(ActivityLog::SEVERITY_WARNING, ActivityLog::TYPE_CHANGE, $message, $data, [IncomakerBundle::LOG_TAG_INCOMAKER]);
        };
    }
}
