<?php

declare(strict_types=1);

namespace ACP\Check;

use AC\Ajax;
use AC\Capabilities;
use AC\Helper\WpDateFormat;
use AC\Message;
use AC\Registerable;
use AC\Screen;
use AC\Storage;
use AC\Type\Url\UtmTags;
use ACP;
use ACP\Access\ActivationStorage;
use ACP\ActivationTokenFactory;
use ACP\AdminColumnsPro;
use ACP\Type\Url\AccountFactory;
use DateTime;

class Expired implements Registerable
{
    private AdminColumnsPro $plugin;

    private ActivationTokenFactory $activation_token_factory;

    private ActivationStorage $activation_storage;

    private AccountFactory $account_url_factory;

    public function __construct(
        AdminColumnsPro $plugin,
        ActivationTokenFactory $activation_token_factory,
        ActivationStorage $activation_storage,
        AccountFactory $account_url_factory
    ) {
        $this->plugin = $plugin;
        $this->activation_token_factory = $activation_token_factory;
        $this->activation_storage = $activation_storage;
        $this->account_url_factory = $account_url_factory;
    }

    public function register(): void
    {
        add_action('ac/screen', [$this, 'display']);

        $this->get_ajax_handler()->register();
    }

    private function is_activation_expired(ACP\Type\Activation $activation): bool
    {
        if (! $activation->is_expired() ||
             ! $activation->has_expiry_date()) {
            return false;
        }

        // Prevent overlap with auto-renewal payments and message
        if ($activation->is_auto_renewal() &&
            $activation->is_expired() &&
            $activation->get_expiry_date()->get_expired_seconds() < (7 * DAY_IN_SECONDS)) {
            return false;
        }

        return true;
    }

    private function get_activation(): ?ACP\Type\Activation
    {
        $token = $this->activation_token_factory->create();

        return $token
            ? $this->activation_storage->find($token)
            : null;
    }

    public function display(Screen $screen): void
    {
        if (! $screen->has_screen() || ! current_user_can(Capabilities::MANAGE)) {
            return;
        }

        switch (true) {
            // Inline message on plugin page
            case $screen->is_plugin_screen():
                $activation = $this->get_activation();

                if ($activation && $this->is_activation_expired($activation)) {
                    $notice = new Message\Plugin(
                        $this->get_message($activation->get_expiry_date()->get_value()),
                        $this->plugin->get_basename(),
                        Message::WARNING
                    );
                    $notice->register();
                }

                return;

                // Permanent displayed on settings page
            case $screen->is_admin_screen():
                $activation = $this->get_activation();

                if ($activation && $this->is_activation_expired($activation)) {
                    $notice = new Message\Notice(
                        $this->get_message($activation->get_expiry_date()->get_value()),
                        Message::WARNING
                    );
                    $notice->register();
                }

                return;

                // Dismissible on list table
            case $screen->is_table_screen() && $this->get_dismiss_option()->is_expired():
                $activation = $this->get_activation();

                if ($activation && $this->is_activation_expired($activation)) {
                    $notice = new Message\Notice\Dismissible(
                        $this->get_message($activation->get_expiry_date()->get_value()),
                        $this->get_ajax_handler(),
                        Message::WARNING
                    );
                    $notice->register();
                }

                return;
        }
    }

    private function get_message(DateTime $expiration_date): string
    {
        $expired_on = (string)wp_date(
            WpDateFormat::date(),
            $expiration_date->getTimestamp(),
            // uses wp_timezone() to convert the date to the user's timezone
            wp_timezone()
        );

        $url = new UtmTags($this->account_url_factory->create(), 'expired');

        return sprintf(
            __(
                'Your Admin Columns Pro license has expired on %s. To receive updates, renew your license on the %s.',
                'codepress-admin-columns'
            ),
            '<strong>' . $expired_on . '</strong>',
            sprintf('<a href="%s">%s</a>', esc_url($url->get_url()), __('My Account Page', 'codepress-admin-columns'))
        );
    }

    protected function get_ajax_handler(): Ajax\Handler
    {
        $handler = new Ajax\Handler();
        $handler
            ->set_action('ac_notice_dismiss_expired')
            ->set_callback([$this, 'ajax_dismiss_notice']);

        return $handler;
    }

    protected function get_dismiss_option(): Storage\Timestamp
    {
        return new Storage\Timestamp(
            new Storage\UserMeta('ac_notice_dismiss_expired')
        );
    }

    public function ajax_dismiss_notice(): void
    {
        $this->get_ajax_handler()->verify_request();
        $this->get_dismiss_option()->save(time() + MONTH_IN_SECONDS);
    }

}
