<?php
declare(strict_types=1);

namespace Ekesto\CacheInvalidator\Resolvers;

use Ekesto\CacheInvalidator\ContentVisibility;
use Ekesto\CacheInvalidator\Core\FeatureFlags;
use Ekesto\CacheInvalidator\Settings\SettingsRepository;
use Ekesto\CacheInvalidator\Support\Debug;

/**
 * Resolves flat post-type expansion targets for invalidation flows.
 */
final class PostTypeExpansionResolver
{
    /**
     * Collect configured expansion post types from enabled host post types.
     *
     * @param string[]           $configuredPostTypes Enabled configured host post types.
     * @param SettingsRepository $settingsRepository Settings repository.
     * @return string[]
     */
    public static function collectConfiguredExpandPostTypes(
        array $configuredPostTypes,
        SettingsRepository $settingsRepository
    ): array {
        // Additional Singular Post Types is a premium feature. In a Lite build the
        // stored expand_post_types values are preserved but ignored at runtime.
        if (!FeatureFlags::isPremium()) {
            return [];
        }

        $expandPostTypes = [];

        foreach ($configuredPostTypes as $configuredPostType) {
            $configuredPostType = sanitize_key((string) $configuredPostType);
            if ($configuredPostType === '') {
                continue;
            }

            $config = $settingsRepository->getPostTypeConfig($configuredPostType);
            if ($config === null || !($config['enabled'] ?? true)) {
                continue;
            }

            $configuredExpandTypes = is_array($config['expand_post_types'] ?? null)
                ? $config['expand_post_types']
                : [];

            $expandPostTypes = array_merge($expandPostTypes, $configuredExpandTypes);
        }

        return ContentVisibility::normalizePostTypes($expandPostTypes);
    }

    /**
     * Apply flat post-type expansion to base target post IDs.
     *
     * @param int[]    $targetPostIds Base target post IDs.
     * @param string[] $expandPostTypes Post types to expand.
     * @return int[]
     */
    public static function expandTargetPostIds(array $targetPostIds, array $expandPostTypes): array
    {
        // Defense-in-depth: never apply premium expansion in a Lite build, even if
        // a non-empty list reaches this method through another path.
        if (!FeatureFlags::isPremium()) {
            return ContentVisibility::normalizePostIds($targetPostIds);
        }

        $targetPostIds = ContentVisibility::normalizePostIds($targetPostIds);
        $expandPostTypes = ContentVisibility::normalizePostTypes($expandPostTypes);

        if (empty($expandPostTypes)) {
            return $targetPostIds;
        }

        foreach ($expandPostTypes as $expandPostType) {
            if (!ContentVisibility::isViewablePublicPostType($expandPostType)) {
                Debug::log(sprintf(
                    'post type expansion: %s -> %d targets (total: %d)',
                    $expandPostType,
                    0,
                    count($targetPostIds)
                ));
                continue;
            }

            $expandedIds = PageTargetResolver::getPublishedPostIdsByPostTypeBatched($expandPostType);
            if (!empty($expandedIds)) {
                $targetPostIds = ContentVisibility::normalizePostIds(array_merge($targetPostIds, $expandedIds));
            }

            Debug::log(sprintf(
                'post type expansion: %s -> %d targets (total: %d)',
                $expandPostType,
                count($expandedIds),
                count($targetPostIds)
            ));
        }

        return $targetPostIds;
    }
}
