<?php

namespace Licenzo\ServiceProvider;

use Licenzo\Framework\Foundation\ServiceProvider;
use Licenzo\Helper\Action;
use Licenzo\Model\License;
use Licenzo\Modules\WooCommerce\WooEmailService;
use Licenzo\Services\DunningService;
use Licenzo\Services\Notification\NotificationHookHandler;
use Licenzo\Services\SubscriptionRenewalService;

if (!defined('ABSPATH')) {
    exit;
}

class EventServiceProvider extends ServiceProvider
{
    public const CRON_EXPIRY_CHECK    = 'licenzo_check_expiring_licenses';
    public const CRON_PROCESS_RENEWALS = 'licenzo_process_renewals';
    public const CRON_CHECK_DUNNING    = 'licenzo_check_dunning';

    private const EXPIRY_WARNING_DAYS = [7, 3, 1];

    public function register()
    {
    }

    public function boot()
    {
        NotificationHookHandler::register();
        WooEmailService::register();
        static::scheduleCronEvents();
        static::registerCronHandlers();
    }

    private static function scheduleCronEvents(): void
    {
        add_action('init', function () {
            if (!function_exists('wp_next_scheduled')) {
                return;
            }

            if (!wp_next_scheduled(static::CRON_EXPIRY_CHECK)) {
                wp_schedule_event(time(), 'daily', static::CRON_EXPIRY_CHECK);
            }

            if (!wp_next_scheduled(static::CRON_PROCESS_RENEWALS)) {
                wp_schedule_event(time(), 'twicedaily', static::CRON_PROCESS_RENEWALS);
            }

            if (!wp_next_scheduled(static::CRON_CHECK_DUNNING)) {
                wp_schedule_event(time(), 'daily', static::CRON_CHECK_DUNNING);
            }
        });
    }

    private static function registerCronHandlers(): void
    {
        add_action(static::CRON_EXPIRY_CHECK, [static::class, 'handleExpiringLicenses']);
        add_action(static::CRON_PROCESS_RENEWALS, [SubscriptionRenewalService::class, 'processAllDue']);
        add_action(static::CRON_CHECK_DUNNING, [DunningService::class, 'checkGracePeriodExpiry']);
    }

    public static function handleExpiringLicenses(): void
    {
        foreach (static::EXPIRY_WARNING_DAYS as $days) {
            static::dispatchExpiryWarningsForDay($days);
        }
    }

    private static function dispatchExpiryWarningsForDay(int $days): void
    {
        $targetDate = gmdate('Y-m-d', strtotime("+{$days} days"));

        $licenses = License::where('status', License::STATUS_ACTIVE)
            ->whereNotNull('expire_date')
            ->where('expire_date', '>=', $targetDate . ' 00:00:00')
            ->where('expire_date', '<=', $targetDate . ' 23:59:59')
            ->get();

        foreach ($licenses as $license) {
            $transientKey = "licenzo_expiry_warned_{$license->id}_{$days}";
            if (get_transient($transientKey)) {
                continue;
            }

            Action::do('notification_license_expiry_warning', [
                'license_id' => (int) $license->id,
                'license' => $license->toArray(),
                'customer_id' => (int) $license->customer_id,
                'days_until_expiry' => $days,
                'expire_date' => (string) $license->expire_date,
            ]);

            set_transient($transientKey, '1', DAY_IN_SECONDS);
        }
    }

}
