<?php

namespace KupShop\AdminBundle\Util;

use KupShop\AdminBundle\AdminRegister\AdminRegisterLocator;
use KupShop\KupShopBundle\Util\ArrayUtil;
use Symfony\Component\HttpFoundation\RequestStack;

class ActivityLog
{
    public const TYPE_CHANGE = 'change';
    public const TYPE_SECURITY = 'security';
    public const TYPE_SYNC = 'sync';
    public const TYPE_IMPORT = 'import';
    /** @deprecated Do not use TYPE_EXPORT, because it is not usable (missing definition in TYPES, DB enum...) */
    public const TYPE_EXPORT = 'export';
    public const TYPE_COMMUNICATION = 'communication';
    public const TYPES = [
        self::TYPE_CHANGE, self::TYPE_SECURITY, self::TYPE_SYNC, self::TYPE_IMPORT, self::TYPE_COMMUNICATION,
    ];

    public const SEVERITY_ERROR = 'error';
    public const SEVERITY_WARNING = 'warning';
    public const SEVERITY_NOTICE = 'notice';
    public const SEVERITY_SUCCESS = 'success';
    public const SEVERITY_RECOMMENDATION = 'recommendation';
    public const SEVERITIES = [
        self::SEVERITY_ERROR, self::SEVERITY_WARNING, self::SEVERITY_NOTICE, self::SEVERITY_SUCCESS, self::SEVERITY_RECOMMENDATION,
    ];

    public function __construct(
        private LegacyAdminCredentials $legacyAdminCredentials,
        private RequestStack $requestStack,
        private readonly AdminRegisterLocator $adminRegisterLocator,
    ) {
    }

    public function addActivityLog(string $severity, string $type, string $message, array $data = [], ?array $tags = [])
    {
        // HOTFIX: Incomaker - při timeoutu není session, v GraphQL se pak "přidá" na konec html s exception a parsování jsonu na tom spadne
        try {
            $adminId = $this->legacyAdminCredentials->getAdminID();
            $isLogged = $this->legacyAdminCredentials->isLogged();
            $admin = getAdminUser();
        } catch (\RuntimeException $e) {
            $adminId = 0;
            $isLogged = false;
        }

        $adminName = ($isLogged && $admin) ? $admin['login'] : 'Robot';
        $message = trim(stripTags(ucfirst($message)));
        if ($tags && isDevelopment()) {
            $activityLogTags = $this->adminRegisterLocator->getActivityLogTags();
            $activityLogTags = array_combine(array_column($activityLogTags, 'tag'), $activityLogTags);
            foreach ($tags as $tag) {
                assert(array_key_exists($tag, $activityLogTags), "wrong tag: {$tag}");
            }
        }

        return sqlGetConnection()->transactional(function () use ($adminId, $adminName, $severity, $type, $message, $data, $tags) {
            sqlQueryBuilder()
                ->insert('report_activities')
                ->directValues(
                    [
                        'id_admin' => $adminId ?: null,
                        'admin_name' => $adminName,
                        'severity' => $severity,
                        'type' => $type,
                        'report' => $message,
                        'ip_address' => explode(',', $this->requestStack->getCurrentRequest()?->getClientIp() ?? '')[0],
                        'data' => json_encode($data, JSON_INVALID_UTF8_IGNORE),
                        'tags' => $tags ? json_encode($tags) : null,
                    ]
                )
                ->setValue('date', 'NOW()')
                ->execute();

            return (int) sqlInsertId();
        });
    }

    public function addDifferencialActivityLog(string $severity, string $type, string $message, $oldData, $newData)
    {
        $diff = ArrayUtil::arrayRecursiveDiff((array) $oldData, (array) $newData);

        $data = ArrayUtil::getSimpleArrayFromDiffs($diff);
        $data = array_filter($data, function ($act) {
            return $act['new'] !== null && $act['new'] !== '';
        });

        return addActivityLog($severity, $type, $message, $data ? ['save_changes' => $data] : []);
    }

    public function addHtmlActivityLog(string $severity, string $type, string $message, $data = [])
    {
        return addActivityLog($severity, $type, $message, $data ? ['html_message' => $data] : []);
    }

    /**
     * @param array<int, string> $data
     *
     * @return array
     */
    public static function addObjectData(array $data, string $type)
    {
        $_objects = [];
        foreach ($data as $k => $v) {
            $_objects['objects'][$type][$k] = $v;
        }

        return $_objects;
    }

    public static function addListLink($listName)
    {
        $_objects['list'] = $listName;

        return $_objects;
    }
}
