<?php

namespace ProudNerds\Admin;

use ProudNerds\Helpers\User;
use ProudNerds\Trait\Initializable;

/**
 * Changes the admin menu.
 */
class AdminMenu
{
    use Initializable;

    private function __construct()
    {
        // Skip if the user is a Proud Nerds admin
        if (User::isProudNerdsAdmin()) {
            add_action('admin_menu', [$this, 'markHiddenMenuItems'], 100);
            add_action('admin_notices', [$this, 'adminNotice']);
            add_action('admin_head', [$this, 'adminNoticeScript']);
            add_action('wp_ajax_pn_hide_admin_notice_admin_menu', [$this, 'hideAdminNotice']);
            return;
        }

        add_action('admin_menu', [$this, 'removeMenuItems']);
        add_action('admin_init', [$this, 'editCapabilities']);
    }

    /**
     * Add a script to hide the admin notice.
     *
     * @return void
     */
    public function adminNoticeScript(): void
    {
        ?>
        <script>
            document.addEventListener('DOMContentLoaded', function () {
                document.getElementById('pn-admin-notice-admin-menu').addEventListener('click', function () {
                    fetch(ajaxurl, {
                        method: 'POST',
                        body: new URLSearchParams({
                            action: 'pn_hide_admin_notice_admin_menu',
                        }),
                    });
                });
            });
        </script>
        <?php
    }

    /**
     * Hide the admin notice about the hidden menu items.
     *
     * @return void
     */
    public function hideAdminNotice(): void
    {
        set_transient('pn_hide_admin_notice_admin_menu', true);
    }

    /**
     * Show an admin notice to the admin to inform about the menu colors
     *
     * @return void
     */
    public function adminNotice()
    {
        if (get_transient('pn_hide_admin_notice_admin_menu')) {
            return;
        }

        $notice = sprintf(
            '<div class="notice notice-warning is-dismissible" id="pn-admin-notice-admin-menu">
                <p>%s</p>
            </div>',
            sprintf('<strong>%s</strong>', __('Let op:', 'proudnerds')) . ' ' .
            sprintf(__('Sommige menu-items zijn roodgekleurd. Deze menu-items (en deze melding) zijn alleen zichtbaar voor gebruikers met de volgende gebruikersnamen: %s.', 'proudnerds'), implode(', ', User::$proudNerdsAdmins))
        );

        echo $notice;
    }

    /**
     * Mark hidden menu items with a color, so we can see which items are hidden for users other than Proud Nerds admins.
     *
     * @return void
     */
    public function markHiddenMenuItems(): void
    {
        global $menu;
        global $submenu;

        // The color to give to hidden menu items
        $color = '#fcbdb8';

        foreach ($menu as $key => $item) {
            if (in_array($item[2], static::menuItemsToHide()['toplevel'])) {
                $menu[$key][0] = sprintf('<span style="color: %s;">%s</span>', $color, $menu[$key][0]);
            }
        }

        foreach (static::menuItemsToHide()['submenu'] as $parent => $items) {
            foreach ($items as $item) {
                foreach ($submenu[$parent] as $key => $subitem) {
                    if ($subitem[2] === $item) {
                        $submenu[$parent][$key][0] = sprintf('<span style="color: %s;">%s</span>', $color, $submenu[$parent][$key][0]);
                    }
                }
            }
        }
    }

    /**
     * Remove menu items from the admin menu.
     *
     * Note: Comments pages are removed in the Comments class.
     *
     * @return void
     */
    public function removeMenuItems(): void
    {
        global $menu;
        global $submenu;

        foreach ($menu as $key => $item) {
            if (in_array($item[2], static::menuItemsToHide()['toplevel'])) {
                unset($menu[$key]);
            }
        }

        foreach (static::menuItemsToHide()['submenu'] as $parent => $items) {
            foreach ($items as $item) {
                foreach ($submenu[$parent] as $key => $subitem) {
                    if ($subitem[2] === $item) {
                        unset($submenu[$parent][$key]);
                    }
                }
            }
        }
    }

    /**
     * Edit the capabilities of the current user.
     *
     * @return void
     */
    public function editCapabilities(): void
    {
        // Get current user
        $user = wp_get_current_user();
        $username = $user->user_login;

        if (get_transient($username . '_admin_menu')) {
            return;
        }

        $remove = [
            'install_plugins',
            'update_plugins',
            'view_plugins',
            'delete_plugins',
            'install_themes',
            'switch_themes',
            'edit_themes',
            'delete_themes',
            'edit_plugins',
            'edit_files',
            'update_themes',
            'update_core',
        ];

        // Remove capabilities
        foreach ($remove as $cap) {
            $user->add_cap($cap, false);
        }

        // Set transient to prevent this from running a lot of queries on every page load
        set_transient($username . '_admin_menu', true, 60 * 60 * 24);
    }

    private static function menuItemsToHide(): array
    {
        return [
            'toplevel' => [
                'plugins.php',
                'edit.php?post_type=acf-field-group',
            ],
            'submenu' => [
                'options-general.php' => [
                    'options-reading.php',
                    'options-media.php',
                    'options-permalink.php',
                    'options-writing.php',
                ],
                'themes.php' => [
                    'themes.php',
                    'customize.php?return=' . urlencode($_SERVER['REQUEST_URI']),
                ],
                'tools.php' => [
                    'site-health.php',
                ],
                'index.php' => [
                    'update-core.php',
                ],
                'theme-options' => [
                    'acf-options-beveiliging',
                ],
            ],
        ];
    }
}
