<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\DependencyInjection;

use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Request;

/**
 * Configure the main bundle.
 */
class Configuration implements ConfigurationInterface
{
    use AddWidgetConfigurationTrait;

    public function __construct(
        array $widgetFactories,
        private readonly ContainerBuilder $containerBuilder,
    ) {
        $this->setWidgetFactories($widgetFactories);
    }

    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder('chill_main');
        $rootNode = $treeBuilder->getRootNode();

        $rootNode
            ->children()
            ->scalarNode('installation_name')
            ->cannotBeEmpty()
            ->defaultValue('Chill')
            ->end() // end of scalar 'installation_name'
            ->arrayNode('available_languages')
            ->defaultValue(['fr'])
            ->prototype('scalar')->end()
            ->end() // end of array 'available_languages'
            ->arrayNode('available_countries')
            ->defaultValue(['FR'])
            ->prototype('scalar')->end()
            ->end() // end of array 'available_countries'
            ->arrayNode('routing')
            ->children()
            ->arrayNode('resources')
            ->prototype('scalar')->end()
            ->end() // end of array 'resources'
            ->end() // end of children
            ->end() // end of array node 'routing'
            ->arrayNode('pagination')
            ->canBeDisabled()
            ->children()
            ->integerNode('item_per_page')
            ->info('The number of item to show in the page result, by default')
            ->min(1)
            ->defaultValue(50)
            ->end() // end of integer 'item_per_page'
            ->end() // end of children
            ->end() // end of pagination
            ->arrayNode('notifications')
            ->children()
            ->scalarNode('from_email')
            ->cannotBeEmpty()
            ->end()
            ->scalarNode('from_name')
            ->cannotBeEmpty()
            ->end()
            ->enumNode('scheme')
            ->cannotBeEmpty()
            ->values(['http', 'https'])
            ->defaultValue('https')
            ->end()
            ->scalarNode('host')
            ->cannotBeEmpty()
            ->end()
            ->end()
            ->end() // end of notifications
            ->arrayNode('workflow_signature')
            ->children()
            ->arrayNode('base_signer')
            ->children()
            ->arrayNode('document_kinds')
            ->arrayPrototype()
            ->children()
            ->scalarNode('key')->cannotBeEmpty()->end()
            ->arrayNode('labels')
            ->arrayPrototype()
            ->children()
            ->scalarNode('lang')->cannotBeEmpty()->end()
            ->scalarNode('label')->cannotBeEmpty()->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end() // end of workflow signature document types
            ->arrayNode('phone_helper')
            ->canBeUnset()
            ->children()
            ->scalarNode('twilio_sid')
            ->defaultNull()
            ->end()
            ->scalarNode('twilio_secret')
            ->defaultNull()
            ->end()
            ->scalarNode('default_carrier_code')
            ->defaultNull()
            ->end()
            ->end()
            ->end()
            ->arrayNode('short_messages')
            ->setDeprecated('chill-project/chill-bundles', '3.7.0', 'Since 3.7.0, Chill use the Notifier component to send message. Configure the notifier instead. In the meantime, the previous available OVH configuration will be append to the notifier component.')
            ->canBeEnabled()
            ->children()
            ->scalarNode('dsn')->cannotBeEmpty()->defaultValue('null://null')
            ->info('the dsn for sending short message. Example: ovh://applicationKey:secret@endpoint')
            ->end()
            ->end()
            ->end() // end for 'short_messages'
            ->arrayNode('acl')
            ->addDefaultsIfNotSet()
            ->children()
            ->booleanNode('form_show_scopes')
            ->defaultTrue()
            ->end()
            ->booleanNode('form_show_centers')
            ->defaultTrue()
            ->end()
            ->booleanNode('filter_stats_by_center')
            ->defaultTrue()
            ->info("if set to false, the exports won't take into account the center of the people")
            ->end()
            ->end()
            ->end() // end of 'acl'
            ->booleanNode('access_global_history')
            ->defaultTrue()
            ->end()
            ->booleanNode('access_user_change_password')
            ->defaultTrue()
            ->end()
            ->booleanNode('access_permissions_group_list')
            ->defaultTrue()
            ->end()
            ->arrayNode('redis')
            ->children()
            ->scalarNode('host')
            ->cannotBeEmpty()
            ->end()
            ->scalarNode('port')
            ->defaultValue(6379)
            ->end()
            ->scalarNode('timeout')
            ->defaultValue(1)
            ->end()
            ->end()
            ->end()
            ->arrayNode('top_banner')
            ->canBeUnset()
            ->children()
            ->booleanNode('visible')
            ->defaultFalse()
            ->end()
            ->arrayNode('text')
            ->useAttributeAsKey('lang')
            ->scalarPrototype()->end()
            ->end() // end of text
            ->scalarNode('color')->defaultNull()->end()
            ->scalarNode('background_color')->defaultNull()->end()
            ->end() // end of top_banner children
            ->end() // end of top_banner
            ->arrayNode('widgets')
            ->canBeEnabled()
            ->canBeUnset()
            ->children()
            ->append($this->addWidgetsConfiguration('homepage', $this->containerBuilder))
            ->end() // end of widgets/children
            ->end() // end of widgets
            ->arrayNode('cruds')
            ->defaultValue([])
            ->arrayPrototype()
            ->children()
            ->scalarNode('class')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('controller')
            ->cannotBeEmpty()
            ->defaultValue(\Chill\MainBundle\CRUD\Controller\CRUDController::class)
            ->end()
            ->scalarNode('name')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('base_path')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('base_role')->defaultNull()->end()
            ->scalarNode('form_class')->defaultNull()->end()
            ->arrayNode('actions')
            ->defaultValue([
                'edit' => [],
                'new' => [],
            ])
            ->useAttributeAsKey('name')
            ->arrayPrototype()
            ->children()
            ->scalarNode('controller_action')
            ->defaultNull()
            ->info('the method name to call in the route. Will be set to the action name if left empty.')
            ->example('action')
            ->end()
            ->scalarNode('path')
            ->defaultNull()
            ->info('the path that will be **appended** after the base path. Do not forget to add '
                                                .'arguments for the method. Will be set to the action name, including an `{id}` '
                                                .'parameter if left empty.')
            ->example('/{id}/my-action')
            ->end()
            ->arrayNode('requirements')
            ->ignoreExtraKeys(false)
            ->info('the requirements for the route. Will be set to `[ \'id\' => \'\d+\' ]` if left empty.')
            ->end()
            ->scalarNode('role')
            ->defaultNull()
            ->info('the role that will be required for this action. Override option `base_role`')
            ->end()
            ->scalarNode('template')
            ->defaultNull()
            ->info('the template to render the view')
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->arrayNode('apis')
            ->defaultValue([])
            ->arrayPrototype()
            ->children()
            ->scalarNode('class')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('controller')
            ->cannotBeEmpty()
            ->defaultValue(\Chill\MainBundle\CRUD\Controller\ApiController::class)
            ->end()
            ->scalarNode('name')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('base_path')->cannotBeEmpty()->isRequired()->end()
            ->scalarNode('base_role')->defaultNull()->end()
            ->arrayNode('actions')
            ->useAttributeAsKey('name')
            ->arrayPrototype()
            ->children()
            ->scalarNode('controller_action')
            ->defaultNull()
            ->info('the method name to call in the controller. Will be set to the concatenation '.
                                                'of action name + \'Api\' if left empty.')
            ->example('showApi')
            ->end()
            ->scalarNode('path')
            ->defaultNull()
            ->info('the path that will be **appended** after the base path. Do not forget to add '.
                                                'arguments for the method. By default, will set to the action name, including an `{id}` '.
                                                'parameter. A suffix of action name will be appended, except if the action name '.
                                                'is "_entity".')
            ->example('/{id}/my-action')
            ->end()
            ->arrayNode('requirements')
            ->ignoreExtraKeys(false)
            ->info('the requirements for the route. Will be set to `[ \'id\' => \'\d+\' ]` if left empty.')
            ->end()
            ->enumNode('single_collection')
            ->values(['single', 'collection'])
            ->defaultValue('single')
            ->info('indicates if the returned object is a single element or a collection. '.
                                                    'If the action name is `_index`, this value will always be considered as '.
                                                    '`collection`')
            ->end()
            ->arrayNode('methods')
            ->addDefaultsIfNotSet()
            ->info('the allowed methods')
            ->children()
            ->booleanNode(Request::METHOD_GET)->defaultTrue()->end()
            ->booleanNode(Request::METHOD_HEAD)->defaultTrue()->end()
            ->booleanNode(Request::METHOD_POST)->defaultFalse()->end()
            ->booleanNode(Request::METHOD_DELETE)->defaultFalse()->end()
            ->booleanNode(Request::METHOD_PUT)->defaultFalse()->end()
            ->booleanNode(Request::METHOD_PATCH)->defaultFalse()->end()
            ->end()
            ->end()
            ->arrayNode('roles')
            ->addDefaultsIfNotSet()
            ->info('The role require for each http method')
            ->children()
            ->scalarNode(Request::METHOD_GET)->defaultNull()->end()
            ->scalarNode(Request::METHOD_HEAD)->defaultNull()->end()
            ->scalarNode(Request::METHOD_POST)->defaultNull()->end()
            ->scalarNode(Request::METHOD_DELETE)->defaultNull()->end()
            ->scalarNode(Request::METHOD_PUT)->defaultNull()->end()
            ->scalarNode(Request::METHOD_PATCH)->defaultNull()->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end()
            ->end() // end of root/children
            ->end() // end of root
        ;

        $rootNode->children()
            ->arrayNode('add_address')->addDefaultsIfNotSet()->children()
            ->scalarNode('default_country')->cannotBeEmpty()->defaultValue('BE')->end()
            ->arrayNode('map_center')->children()
            ->scalarNode('x')->cannotBeEmpty()->defaultValue(50.8443)->end()
            ->scalarNode('y')->cannotBeEmpty()->defaultValue(4.3523)->end()
            ->scalarNode('z')->cannotBeEmpty()->defaultValue(15)->end()
            ->end()
            ->end();

        return $treeBuilder;
    }
}
