<?php

declare(strict_types=1);

namespace Inpsyde\MultilingualPress\Module\User;

use Inpsyde\MultilingualPress\Framework\Http\ServerRequest;
use Inpsyde\MultilingualPress\Framework\Module\Exception\ModuleAlreadyRegistered;
use Inpsyde\MultilingualPress\Framework\Module\ModuleServiceProvider;
use Inpsyde\MultilingualPress\Framework\Module\Module;
use Inpsyde\MultilingualPress\Framework\Module\ModuleManager;
use Inpsyde\MultilingualPress\Framework\Service\Container;
use Inpsyde\MultilingualPress\Module\User\TranslationUi\MetaboxFields;
use Inpsyde\MultilingualPress\Module\User\TranslationUi\MetaboxView;
use Inpsyde\MultilingualPress\Module\User\TranslationUi\MetaboxAction;
use Throwable;
use WP_User;

class ServiceProvider implements ModuleServiceProvider
{
    public const MODULE_ID = 'user';

    /**
     * @inheritdoc
     * @throws ModuleAlreadyRegistered
     */
    public function registerModule(ModuleManager $moduleManager): bool
    {
        return $moduleManager->register(
            new Module(
                self::MODULE_ID,
                [
                    'description' => __(
                        'Enable the user information translation settings.',
                        'multilingualpress'
                    ),
                    'name' => __('User Information Translation Settings', 'multilingualpress'),
                    'active' => false,
                ]
            )
        );
    }

    /**
     * @inheritdoc
     */
    public function register(Container $container)
    {
        $container->share(
            MetaboxView::class,
            static function (): MetaboxView {
                return new MetaboxView(
                    new MetaboxFields()
                );
            }
        );

        $container->share(
            MetaboxAction::class,
            static function (): MetaboxAction {
                return new MetaboxAction();
            }
        );

        $container->share(
            MetaValueFilter::class,
            static function (): MetaValueFilter {
                return new MetaValueFilter();
            }
        );

        $container->share(
            MetaboxFields::class,
            static function (): MetaboxFields {
                return new MetaboxFields();
            }
        );
    }

    /**
     * @inheritdoc
     * @throws Throwable
     */
    public function activateModule(Container $container)
    {
        $metaValueFilter = $container->get(MetaValueFilter::class);
        $metaboxFields = $container->get(MetaboxFields::class);

        $this->filterUserMetaValues($metaValueFilter, $metaboxFields);

        if (!is_admin()) {
            return;
        }

        $metaboxView = $container->get(MetaboxView::class);
        $request = $container->get(ServerRequest::class);
        $metaboxAction = $container->get(MetaboxAction::class);

        $this->metaboxViewActions($metaboxView);
        $this->metaboxUpdateActions($request, $metaboxAction);
    }

    /**
     * Render MultilingualPress custom metaboxes on user profile pages.
     *
     * @param MetaboxView $metaboxView
     */
    protected function metaboxViewActions(MetaboxView $metaboxView)
    {
        add_action('show_user_profile', static function (WP_User $user) use ($metaboxView) {
            $metaboxView->render($user);
        });
        add_action('edit_user_profile', static function (WP_User $user) use ($metaboxView) {
            $metaboxView->render($user);
        });
    }

    /**
     * Handles the actions when the user profile page is updated.
     *
     * When the user profile page is updated we need to save our custom translation meta.
     *
     * @param ServerRequest $request
     * @param MetaboxAction $metaboxAction
     */
    protected function metaboxUpdateActions(ServerRequest $request, MetaboxAction $metaboxAction)
    {

        add_action(
            'personal_options_update',
            static function (int $userId) use ($metaboxAction, $request) {
                $metaboxAction->updateTranslationData($userId, $request);
            }
        );
        add_action(
            'edit_user_profile_update',
            static function (int $userId) use ($metaboxAction, $request) {
                $metaboxAction->updateTranslationData($userId, $request);
            }
        );
    }

    /**
     * Filters the frontend values for user meta fields and replaces with correct translations.
     *
     * @param MetaValueFilter $metaValueFilter
     * @param MetaboxFields $metaboxFields
     */
    protected function filterUserMetaValues(MetaValueFilter $metaValueFilter, MetaboxFields $metaboxFields)
    {
        foreach ($metaboxFields->allFields() as $key => $field) {
            add_filter("the_author_{$key}", [$metaValueFilter, 'filterMetaValues'], 10, 2);
            add_filter("get_the_author_{$key}", [$metaValueFilter, 'filterMetaValues'], 10, 2);
        }
    }
}
