<?php

namespace GravityKit\GravityExport\Routing;

use GFExcel\Routing\Request;
use GFExcel\Routing\Router;
use GFExcel\Routing\WordPressRouter;

/**
 * Router for Gravity Export.
 *
 * It augments the WordPress router with additional endpoints and configuration.
 *
 * @since 1.5.0
 */
final class GravityExportRouter implements Router
{
    /**
     * The default action.
     *
     * @since 1.5.0
     *
     * @var string
     */
    public const DEFAULT_ACTION = 'gravityexport';

    /**
     * The WordPress router.
     *
     * @since 1.5.0
     * @var WordPressRouter
     */
    private $router;

    /**
     * Creates the Gravity Export router.
     *
     * @since 1.5.0
     *
     * @param Router|null $router An optional delegation router.
     *
     */
    public function __construct( Router $router = null )
    {
        $this->router = $router ?? new WordPressRouter();
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function init(): void
    {
        if ( ! $this->router instanceof WordPressRouter ) {
            return;
        }

        $this->router->register_endpoints( $this->endpoints() );
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function endpoints(): array
    {
        $endpoints = $this->router->endpoints();

        // Add the default action.
        $default_slug = $this->get_default_endpoint();
        if ( ! in_array( $default_slug, $endpoints, true ) ) {
            $endpoints[] = $default_slug;
        }

        /**
         * @filter `gk/gravityexport/router/endpoints` Modify the list of download endpoints.
         *
         * @since 1.5.0
         *
         * @param array $endpoints The list of endpoints.
         */
        $endpoints = apply_filters( 'gk/gravityexport/router/endpoints', $endpoints );

        return array_values( array_unique( $endpoints ) );
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function get_url_for_form( int $form_id ): ?string
    {
        $url = $this->router->get_url_for_form( $form_id );

        return $url ? $this->replace_action_slug( $url ) : null;
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function get_url_for_hash( string $hash ): string
    {
        $url = $this->router->get_url_for_hash( $hash );

        return $this->replace_action_slug( $url );
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function matches( Request $request ): bool
    {
        if ( in_array( $request->action(), $this->endpoints(), true ) ) {
            return true;
        }

        return $this->router->matches( $request );
    }

    /**
     * @inheritDoc
     * @since 1.5.0
     */
    public function get_feed_by_request( Request $request ): ?array
    {
        return $this->router->get_feed_by_request( $request );
    }

    /**
     * Returns the default action URL.
     *
     * @since 1.5.0
     */
    public function get_default_endpoint(): string
    {
        /**
         * @filter `gk/gravityexport/router/default_endpoint` Modify the default action slug.
         *
         * @since 1.5.0
         */
        return apply_filters( 'gk/gravityexport/router/default_endpoint', self::DEFAULT_ACTION );
    }

    /**
     * Replaces the default action slug with the default action slug.
     *
     * @since 1.5.0
     *
     * @param string $url
     *
     * @return string
     */
    private function replace_action_slug( string $url ): string
    {
        return str_replace( WordPressRouter::DEFAULT_ACTION, $this->get_default_endpoint(), $url );
    }
}
