<?php
/**
 * Free-tier helpers — build-time differentiation.
 *
 * The free WordPress.org zip is a genuinely smaller build, NOT a license-gated
 * one (WP.org forbids gating present features behind a license). build.py
 * injects `INSTINCTOR_FREE_TIER` into the free zip and strips every
 * `PRO-START … PRO-END` region below, so the free build ships ONLY the static
 * list branches — zero license/tier-check logic. Standalone and the licensed
 * Pro build (-pro.zip, self-distributed) keep the TierManager-driven branches.
 *
 * Mechanisms, by feature:
 *   - STRIP   : Pro-only code removed from the free zip (catalog effects, etc.).
 *   - CAP     : present-but-limited via instinctor_locked()/build-time constant.
 *   - WATERMARK: premium 3D/depth output is marked in free (instinctor_free_watermark()).
 *
 * @package Instinctor
 */

if (!defined('ABSPATH')) { exit; }

// Pro feature slugs LOCKED in the free build. 3D depth + environments are NOT
// in this list because they are handled separately (2026-07-05): they render
// live in the EDITOR as a Pro demo but PUBLISH FLAT on the free build
// (instinctor_env_locked() returns true on the front-end path). No watermark.
if (!defined('INSTINCTOR_FREE_LOCKED')) {
    define('INSTINCTOR_FREE_LOCKED', array(
        'section_fx',
        'chat_pro',
        'seo_advanced',
        'network',
        // Premium commerce suite — the WooCommerce paid-extension equivalents.
        // The basic store stays free: products (unlimited), cart, a working
        // standard checkout, Stripe, AND all the visible product/cart effects
        // (flip cards, side cart) — visible beauty is never locked. Pro gates the
        // FUNCTIONAL extensions WC charges for.
        'custom_checkout',     // configurable checkout field grid / layout / styling
        'store_subscriptions', // recurring billing (wired at the product editor)
        'store_bundles',       // product bundles / build-your-own
        'store_bookings',      // service booking
    ));
}

/**
 * Signature motion features that PUBLISH FLAT on the free WordPress.org build.
 *
 * Same shape as the 3D/environment demo above, and for the same reason: the
 * builder renders them in full so the author sees exactly what they do, and the
 * published page renders without them. Nothing is watermarked and nothing is
 * branded on the visitor's site, so WP.org Guideline 10 is not engaged, and a
 * reviewer sees a feature that is absent from the free tier rather than a
 * crippled one nagging for an upgrade.
 *
 * Callers MUST pass the editor flag: the gate is front-end only. Sergei
 * 2026-08-07.
 */
function instinctor_motion_demo_locked(bool $isEditor = false): bool {
    if ($isEditor) return false;                 // builder always shows the real thing
    
    return true;
}

/** True only in the stripped free WordPress.org build. */
function instinctor_is_free_build(): bool {
    return defined('INSTINCTOR_FREE_TIER') && INSTINCTOR_FREE_TIER;
}

/** Is a Pro feature slug locked in THIS build? */
function instinctor_locked(string $feature): bool {
    
    return in_array($feature, INSTINCTOR_FREE_LOCKED, true);
}

/** Is a cloud/environment effect locked in THIS build? */
function instinctor_env_locked(string $effect): bool {
    
    // WP.org free build (2026-07-05): 3D/depth environments are an EDITOR-ONLY
    // demo, never published. This gate runs only on the FRONT-END render path
    // (impulse-page.php; impulse-animation-helpers guards it with !$isPreview),
    // so returning true publishes flat pages while the editor preview
    // (impulse-preview.php, which never calls this) still shows live 3D.
    return true;
}

/** Should premium 3D / depth OUTPUT carry the free-tier watermark in THIS build? */
function instinctor_free_watermark(): bool {
    
    // No watermark on the free build. 3D/depth is an editor-only demo now, so
    // there is no published output to mark, and forced front-end branding would
    // violate WP.org Guideline 10.
    return false;
}

/** Editor's notion of "licensed" (drives Pro-upsell affordances). Free build = false. */
function instinctor_editor_has_license(): bool {
    
    return false;
}

/** Build-time replacement for TierManager::isPro(). Free build = false (no license call). */
function instinctor_has_pro(): bool {
    
    return false;
}

/** Build-time replacement for TierManager::tier(). Free build = 'free' (no license call). */
function instinctor_tier(): string {
    
    return 'free';
}

/**
 * May this render emit real 3D depth?
 *
 * 3D depth is a Pro capability, and Pro means the owner's OWN standalone
 * install. On the shared host (instinctor.com/<slug>) a free tenant publishes
 * flat: they were getting the depth engine for nothing because the only gate
 * ever written for it, TierManager::canDepthImage(), had no callers and
 * canFeature() answers "unlocked" for every standalone environment (a comment
 * from when standalone meant paid-only, which the free-publish model retired).
 *
 * Deliberately narrow, so it can never reach a paying site:
 *   - apex instinctor.com ONLY. A client's own standalone runs on its own
 *     domain, returns early here, and is untouched.
 *   - demos keep depth: it is the pitch, and they have no owner anyway.
 *   - the builder keeps depth: it is our tool, not a published page.
 *   - vendor / ownerless pages keep depth.
 * A free owner's EDIT view is flattened too, on purpose: what they edit has to
 * be what visitors see, or the live page reads as broken.
 */
/**
 * REVISED 2026-07-26 (Sergei): free tenants DO get depth on their hero, but only on
 * OUR images. Flattening their published site meant the demo showed a moving hero and
 * the site they got did not, which reframed what they had just made as the broken
 * version. The Pro line sits elsewhere and is plenty: the editor, instant booking,
 * unlimited chat, reminders.
 *
 * What free never gets is depth on a CUSTOM image. A depth map has to be generated per
 * image, so an owner upload has none, and pointing the shader at a missing map is a
 * broken hero rather than a cheap one.
 *
 * WHITELIST, not blacklist: only our curated roots qualify, so any future upload
 * location is denied by default rather than silently inheriting depth.
 */
function impulse_depth_is_curated_image(string $path): bool {
    if ($path === '') return false;
    $p = strtolower(parse_url($path, PHP_URL_PATH) ?: $path);
    // Our own libraries: /storage/uploads/<vertical>-presets/... and the shared
    // vertical image library. Everything else, including anything an owner uploads,
    // is custom.
    if (strpos($p, '/instinctor-images/') !== false) return true;
    return (bool) preg_match('#/storage/uploads/[a-z0-9_-]*presets?/#', $p);
}

function impulse_can_render_depth(string $depthImage = ''): bool {
    if (!class_exists('\Instinctor\Core\Plugin')
        || !\Instinctor\Core\Plugin::isInstinctorApp()) return true;      // not the shared host
    if (!empty($GLOBALS['impulse_is_demo'])) return true;                 // the pitch
    if (class_exists('\Instinctor\Core\TierManager')
        && \Instinctor\Core\TierManager::isAdminContext()) return true;   // builder / preview
    $ownerId = class_exists('\Instinctor\Core\Tenant')
        ? (int) \Instinctor\Core\Tenant::currentOwnerId() : 0;
    if ($ownerId <= 0) return true;                                       // vendor pages
    if (class_exists('\Instinctor\Core\TenantPlan')
        && \Instinctor\Core\TenantPlan::isPro($ownerId)) return true;    // Pro: anything
    // Free tenant: our images yes, their own uploads no. An empty path is the caller
    // asking the old question ("may this owner have depth at all?") - answer yes, and
    // let the per-image check below decide when it passes one.
    return $depthImage === '' ? true : impulse_depth_is_curated_image($depthImage);
}
