<?php
namespace EasyChat\Model\Cms;

use EasyChat\Library\Catalog\CatalogUrlPolicy;
use EasyChat\Library\Logger;





abstract class CmsModelBase implements CmsInterface {

    protected $db;
    protected $prefix;
    protected $settings;

    public function __construct($db, string $prefix, array $settings) {
        if (!preg_match('/^[A-Za-z0-9_]{0,64}$/', $prefix)) {
            throw new \InvalidArgumentException('Недопустимый префикс таблиц CMS.');
        }
        $this->db     = $db;
        $this->prefix = $prefix;
        $this->settings = $settings;
    }

     
     
     

    



    protected function getSearchLimit(): int {
        return max(1, min(50, (int)($this->settings['chat_cms_search_limit'] ?? 5)));
    }

    



    protected function splitWords(string $query): array {
        $query = preg_replace('/[\x00-\x1F\x7F]+/u', ' ', $query);
        $query = mb_substr(trim((string)$query), 0, 160, 'UTF-8');
        $words = preg_split('/\s+/u', mb_strtolower($query, 'UTF-8'));
        $words = array_values(array_filter($words, function (string $w): bool {
            return mb_strlen($w, 'UTF-8') > 2;
        }));
        $words = array_slice(array_values(array_unique($words)), 0, 8);
        return !empty($words) ? $words : [mb_strtolower($query, 'UTF-8')];
    }

     
    protected function normalizeSearchIdentifier(string $value): string {
        $value = mb_strtolower(trim($value), 'UTF-8');
        $value = str_replace('\\', '', $value);
        return (string)preg_replace('/[\s\-_.\/]+/u', '', $value);
    }

    




    protected function compactSearchIdentifierSql(string $expression): string {
        return "LOWER(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE({$expression}, ''), '-', ''), '/', ''), '_', ''), '.', ''), ' ', ''))";
    }

     
    protected function escapeLikeWord(string $value): string {
        $value = str_replace(array('\\', '%', '_'), array('\\\\', '\\%', '\\_'), $value);
        return $this->db->escape($value);
    }

     
     
     

    







    protected function getBaseUrl(): string {
        $base_url   = '';
        $parent_dir = defined('SITE_PATH')
            ? dirname(SITE_PATH)
            : dirname(dirname(dirname(__DIR__)));

        $parent_config = $parent_dir . DIRECTORY_SEPARATOR . 'config.php';
        if (file_exists($parent_config)) {
            $cfg = file_get_contents($parent_config);
            if (preg_match("/define\s*\(\s*['\"]HTTP_CATALOG['\"]\s*,\s*['\"]([^'\"]+)['\"]\s*\)/i", $cfg, $m)) {
                $base_url = CatalogUrlPolicy::normalizeBaseUrl((string)$m[1]);
            } elseif (preg_match("/define\s*\(\s*['\"]HTTP_SERVER['\"]\s*,\s*['\"]([^'\"]+)['\"]\s*\)/i", $cfg, $m)) {
                $base_url = CatalogUrlPolicy::normalizeBaseUrl((string)$m[1]);
            }
        }

        if (!$base_url) {
            $fwd_proto = strtolower(\EasyChat\Library\RequestContext::server()['HTTP_X_FORWARDED_PROTO'] ?? '');
            $fwd_ssl   = strtolower(\EasyChat\Library\RequestContext::server()['HTTP_X_FORWARDED_SSL']   ?? '');
            $https     = (!empty(\EasyChat\Library\RequestContext::server()['HTTPS']) && \EasyChat\Library\RequestContext::server()['HTTPS'] !== 'off')
                      || ((\EasyChat\Library\RequestContext::server()['SERVER_PORT'] ?? 80) == 443)
                      || $fwd_proto === 'https'
                      || $fwd_ssl   === 'on';
            $host = \EasyChat\Library\RequestContext::server()['HTTP_HOST'] ?? '';
            if ($host && strpos($host, 'index.php') === false) {
                $script_dir = rtrim(dirname(\EasyChat\Library\RequestContext::server()['SCRIPT_NAME'] ?? ''), '/\\');
                $base_path  = preg_replace('/\/easychat(\/.*)?$/i', '', $script_dir);
                $base_url   = CatalogUrlPolicy::normalizeBaseUrl(
                    ($https ? 'https://' : 'http://') . $host . $base_path
                );
            }
        }

        if (!$base_url && defined('HTTP_SERVER')) {
            $base_url = CatalogUrlPolicy::normalizeBaseUrl((string)HTTP_SERVER);
            $base_url = preg_replace('/\/easychat$/i', '', $base_url);
        }

        return $base_url;
    }

    




    public function resolvePublicUrls(array $items, string $resource_type): array {
        foreach ($items as &$item) {
            if (!is_array($item)) {
                continue;
            }
            $link = trim((string)($item['link'] ?? $item['url'] ?? ''));
            if (!CatalogUrlPolicy::isSafeLink($link)) {
                $link = '';
            }
            $item['link'] = $link;
            if (isset($item['url'])) {
                $item['url'] = $link;
            }
        }
        unset($item);
        return $items;
    }

    protected function resolveSinglePublicUrl(string $resource_type, int $id, string $technical_url): string {
        $rows = $this->resolvePublicUrls(array(array(
            'id' => (string)$id,
            'link' => $technical_url,
        )), $resource_type);
        $resolved = trim((string)($rows[0]['link'] ?? ''));
        return CatalogUrlPolicy::isSafeLink($resolved) ? $resolved : $technical_url;
    }

     
     
     

    


    protected function log(string $message): void {
        
        if (!defined('SITE_PATH')) {
            return ;
        }

        $isLoging = $this->settings['chat_cms_logging'] ?? false;
        
        if(!$isLoging)
            return ;

        Logger::write($message, 'search.log');

    }

     
    protected function logFailure(string $event, \Throwable $error): void {
        $class = preg_replace('/[^A-Za-z0-9_\\-]/', '', get_class($error));
        $fingerprint = substr(hash('sha256', $error->getMessage()), 0, 12);
        $this->log($event . ' exception=' . $class . ' fingerprint=' . $fingerprint);
    }
}
