<?php

namespace Components\Support;

/**
 * Unified flow HTML cache backed by a dedicated DB table.
 */
class FlowHtmlCache
{
    public const OWNER_NEWSLETTER_ITEM = 'newsletter_item';
    public const OWNER_AUDIENCE = 'audience';
    public const OWNER_MODULE = 'module';
    public const OWNER_NEWSLETTER_ITEM_PERFORMANCE = 'newsletter_item_perf';
    public const OWNER_AUDIENCE_PERFORMANCE = 'audience_perf';
    public const OWNER_MODULE_PERFORMANCE = 'module_perf';

    protected static function getTableName(): string
    {
        if (!defined('TABLE_MAILBEEZ_FLOW_CACHE')) {
            mh_define('TABLE_MAILBEEZ_FLOW_CACHE', DB_PREFIX . 'mailbeez_flow_cache');
        }
        return TABLE_MAILBEEZ_FLOW_CACHE;
    }

    protected static function normalizeOwnerId($ownerId): string
    {
        if (is_int($ownerId) || is_float($ownerId)) {
            return (string)(int)$ownerId;
        }
        return trim((string)$ownerId);
    }

    /**
     * Normalize HTML payloads that may be persisted with slash-escaped quotes
     * on some legacy DB wrappers (e.g. class=\"...\").
     */
    protected static function normalizeFlowHtml($html)
    {
        if (!is_string($html) || $html === '') {
            return $html;
        }

        // Keep the operation conservative: only unslash when the payload clearly
        // looks like escaped HTML markup.
        if (strpos($html, '\\"') === false) {
            return $html;
        }

        $unslashed = stripslashes($html);
        if ($unslashed === '' || $unslashed === $html) {
            return $html;
        }

        if (strpos($unslashed, '<') !== false && strpos($unslashed, '="') !== false) {
            return $unslashed;
        }

        return $html;
    }

    public static function get(string $ownerType, $ownerId, string $lang = 'default')
    {
        $ownerType = trim($ownerType);
        $ownerId = static::normalizeOwnerId($ownerId);
        $lang = trim($lang) !== '' ? trim($lang) : 'default';

        if ($ownerType === '' || $ownerId === '') {
            return false;
        }

        $table = static::getTableName();
        $query = mh_db_query(
            "select flow_html from " . $table . " where owner_type = '" . mh_db_input($ownerType) . "'"
            . " and owner_id = '" . mh_db_input($ownerId) . "'"
            . " and lang = '" . mh_db_input($lang) . "'"
            . " limit 1"
        );

        if (mh_db_num_rows($query) < 1) {
            return false;
        }

        $row = mh_db_fetch_array($query);
        $html = $row['flow_html'] ?? false;
        return static::normalizeFlowHtml($html);
    }

    public static function has(string $ownerType, $ownerId, string $lang = 'default'): bool
    {
        $cached = static::get($ownerType, $ownerId, $lang);
        return is_string($cached) && $cached !== '';
    }

    public static function set(string $ownerType, $ownerId, string $lang, string $html): void
    {
        $ownerType = trim($ownerType);
        $ownerId = static::normalizeOwnerId($ownerId);
        $lang = trim($lang) !== '' ? trim($lang) : 'default';

        if ($ownerType === '' || $ownerId === '') {
            return;
        }

        $table = static::getTableName();

        $html = (string)static::normalizeFlowHtml($html);

        mh_db_query(
            "insert into " . $table . " (owner_type, owner_id, lang, flow_html, updated_at) values ("
            . "'" . mh_db_input($ownerType) . "', "
            . "'" . mh_db_input($ownerId) . "', "
            . "'" . mh_db_input($lang) . "', "
            . "'" . mh_db_input($html) . "', now())"
            . " on duplicate key update flow_html = values(flow_html), updated_at = values(updated_at)"
        );
    }

    public static function invalidateOwner(string $ownerType, $ownerId): void
    {
        $ownerType = trim($ownerType);
        $ownerId = static::normalizeOwnerId($ownerId);

        if ($ownerType === '' || $ownerId === '') {
            return;
        }

        $table = static::getTableName();
        mh_db_query(
            "delete from " . $table . " where owner_type = '" . mh_db_input($ownerType) . "'"
            . " and owner_id = '" . mh_db_input($ownerId) . "'"
        );
    }

    public static function invalidateType(string $ownerType): void
    {
        $ownerType = trim($ownerType);
        if ($ownerType === '') {
            return;
        }

        $table = static::getTableName();
        mh_db_query("delete from " . $table . " where owner_type = '" . mh_db_input($ownerType) . "'");
    }
}
