<?php

namespace Notifal\Modules\Campaign\Presentation\Admin\Routes;

defined( 'ABSPATH' ) || exit;

use Notifal\Modules\Campaign\Application\Services\CampaignService;
use Notifal\Shared\AdminUI\Toast\ToastManager;
use Notifal\Shared\AdminUI\Traits\AdminOperationsTrait;
use Notifal\Shared\Utils\Helper;

/**
 * Class AdminRouteController
 *
 * Handles admin-side routes for campaigns dispatched via `admin_init`.
 * Wires delete, duplicate, and empty-trash URLs generated by `BaseListView`
 * so they redirect back to the campaigns list with toast feedback.
 *
 * @since 2.0.0
 * @author Hossein <hossein@notifal.com>
 */
class AdminRouteController
{
    use AdminOperationsTrait;

    /**
     * Hook prefix for action hooks (used by `AdminOperationsTrait::triggerHook`).
     *
     * @var string
     */
    protected const HOOK_PREFIX = 'Notifal\\Infrastructure\\WordPress\\Hooks\\ActionHooks::';

    /**
     * Campaign post type slug.
     *
     * @var string
     */
    protected const POST_TYPE = 'notifal_campaign';

    /**
     * Admin page slug for the campaigns list screen.
     *
     * @var string
     */
    protected const LIST_PAGE = 'notifal-campaigns';

    /**
     * Registers the admin route dispatcher on `admin_init`.
     *
     * @since 2.0.0
     * @return void
     */
    public static function register(): void
    {
        add_action( 'admin_init', [ self::class, 'dispatch' ] );
    }

    /**
     * Dispatches GET `action` requests to the appropriate handler.
     *
     * @since 2.0.0
     * @return void
     */
    public static function dispatch(): void
    {
        if ( ! is_admin() ) {
            return;
        }

        $action = Helper::sanitizeInput( $_GET['action'] ?? '', 'text' );

        switch ( $action ) {
            case 'notifal_delete_notifal_campaign':
                self::handleDeleteCampaign();
                break;

            case 'notifal_duplicate_notifal_campaign':
                self::handleDuplicateCampaign();
                break;

            case 'notifal_empty_trash_notifal_campaign':
                self::handleEmptyTrashCampaign();
                break;
        }
    }

    /**
     * Builds the redirect URL back to the campaigns list, preserving status tab.
     *
     * @since 2.0.0
     * @param string $status Optional status filter (`trash`, etc.).
     * @return string Full admin URL.
     */
    protected static function getCampaignListRedirectUrl( string $status = '' ): string
    {
        $url = admin_url( 'admin.php?page=' . self::LIST_PAGE );
        if ( $status !== '' ) {
            $url = add_query_arg( 'status', rawurlencode( $status ), $url );
        }
        return $url;
    }

    /**
     * Deletes a single campaign (trash or permanent) with nonce and capability checks.
     *
     * Move-to-trash uses `CampaignService::delete()` so linked notifications are unlinked.
     * Permanent delete from the trash view uses `wp_delete_post()` (notifications were
     * already unlinked when the campaign was trashed).
     *
     * @since 2.0.0
     * @return void
     */
    protected static function handleDeleteCampaign(): void
    {
        $post_id = absint( $_GET['id'] ?? 0 );
        $nonce   = Helper::sanitizeInput( $_GET['_wpnonce'] ?? '', 'key' );
        $status  = Helper::sanitizeInput( $_GET['status'] ?? '', 'text' );

        $redirect_url = self::getCampaignListRedirectUrl( $status );

        if ( ! $post_id || get_post_type( $post_id ) !== self::POST_TYPE ) {
            ToastManager::error( __( 'Invalid post ID.', 'notifal' ), $redirect_url );
            return;
        }

        if ( ! wp_verify_nonce( $nonce, 'delete_notifal_campaign_' . $post_id ) ) {
            ToastManager::error( __( 'Security check failed.', 'notifal' ), $redirect_url );
            return;
        }

        if ( ! current_user_can( 'delete_post', $post_id ) ) {
            ToastManager::error( __( 'You do not have permission to delete this campaign.', 'notifal' ), $redirect_url );
            return;
        }

        if ( $status === 'trash' ) {
            $result  = wp_delete_post( $post_id, true );
            $message = __( 'Post permanently deleted.', 'notifal' );
        } else {
            $campaign_service = notifal_app( CampaignService::class );
            $result           = $campaign_service->delete( $post_id );
            $message          = __( 'Post moved to trash.', 'notifal' );
        }

        if ( ! $result ) {
            ToastManager::error( __( 'Failed to delete post.', 'notifal' ), $redirect_url );
            return;
        }

        ToastManager::success( $message, $redirect_url );
    }

    /**
     * Duplicates a campaign using shared trait logic (meta, terms, toast redirect).
     *
     * @since 2.0.0
     * @return void
     */
    protected static function handleDuplicateCampaign(): void
    {
        $post_id = absint( $_GET['id'] ?? 0 );

        self::handleDuplicatePost(
            $post_id,
            'duplicate_notifal_campaign_' . $post_id,
            self::POST_TYPE,
            function ( $status ) {
                return self::getCampaignListRedirectUrl( is_string( $status ) ? $status : '' );
            },
            ''
        );
    }

    /**
     * Permanently deletes all campaigns in the trash for this post type.
     *
     * @since 2.0.0
     * @return void
     */
    protected static function handleEmptyTrashCampaign(): void
    {
        self::handleEmptyTrash(
            self::POST_TYPE,
            'empty_trash_notifal_campaign',
            function ( $status = '' ) {
                if ( $status === 'trash' ) {
                    return self::getCampaignListRedirectUrl( 'trash' );
                }
                return self::getCampaignListRedirectUrl();
            },
            ''
        );
    }
}
