<?php

declare (strict_types=1);
namespace PoP\ComponentModel\TypeResolvers;

use PoP\Root\App;
use PoP\ComponentModel\Module;
use PoP\ComponentModel\ModuleConfiguration;
use PoP\ComponentModel\FieldResolvers\InterfaceType\InterfaceTypeFieldResolverInterface;
use PoP\ComponentModel\FieldResolvers\ObjectType\ObjectTypeFieldResolverInterface;
use PoP\ComponentModel\TypeResolvers\InterfaceType\InterfaceTypeResolverInterface;
use PoP\ComponentModel\TypeResolvers\ObjectType\ObjectTypeResolverInterface;
/** @internal */
trait ExcludeFieldNamesFromSchemaTypeResolverTrait
{
    /**
     * Call a hook to allow removing fields from the schema
     *
     * @return string[]
     * @param string[] $fieldNames
     */
    protected function maybeExcludeFieldNamesFromSchema(ObjectTypeResolverInterface|InterfaceTypeResolverInterface $objectTypeOrInterfaceTypeResolver, ObjectTypeFieldResolverInterface|InterfaceTypeFieldResolverInterface $objectTypeOrInterfaceTypeFieldResolver, array $fieldNames) : array
    {
        // Enable to exclude fieldNames, so they are not added to the schema.
        $excludedFieldNames = [];
        // Whenever:
        // 1. Exclude the sensitive fields, if not enabled by env var
        /** @var ModuleConfiguration */
        $moduleConfiguration = App::getModule(Module::class)->getConfiguration();
        if (!$moduleConfiguration->exposeSensitiveDataInSchema()) {
            $excludedFieldNames = $objectTypeOrInterfaceTypeFieldResolver->getSensitiveFieldNames();
        }
        // 2. By filter hook
        $excludedFieldNames = App::applyFilters(\PoP\ComponentModel\TypeResolvers\Hooks::EXCLUDE_FIELDNAMES, $excludedFieldNames, $objectTypeOrInterfaceTypeFieldResolver, $fieldNames);
        if ($excludedFieldNames !== []) {
            $fieldNames = \array_values(\array_diff($fieldNames, $excludedFieldNames));
        }
        // Execute a hook, allowing to filter them out (eg: removing fieldNames from a private schema)
        // Also pass the Interfaces defining the field
        $fieldNames = \array_filter($fieldNames, fn($fieldName) => $this->isFieldNameResolvedByObjectTypeFieldResolver($objectTypeOrInterfaceTypeResolver, $objectTypeOrInterfaceTypeFieldResolver, $fieldName));
        return $fieldNames;
    }
    protected function isFieldNameResolvedByObjectTypeFieldResolver(ObjectTypeResolverInterface|InterfaceTypeResolverInterface $objectTypeOrInterfaceTypeResolver, ObjectTypeFieldResolverInterface|InterfaceTypeFieldResolverInterface $objectTypeOrInterfaceTypeFieldResolver, string $fieldName) : bool
    {
        // Execute 2 filters: a generic one, and a specific one
        if (App::applyFilters(\PoP\ComponentModel\TypeResolvers\HookHelpers::getHookNameToFilterField(), \true, $objectTypeOrInterfaceTypeResolver, $objectTypeOrInterfaceTypeFieldResolver, $fieldName)) {
            return App::applyFilters(\PoP\ComponentModel\TypeResolvers\HookHelpers::getHookNameToFilterField($fieldName), \true, $objectTypeOrInterfaceTypeResolver, $objectTypeOrInterfaceTypeFieldResolver, $fieldName);
        }
        return \false;
    }
}
