<?php

namespace WeDevs\Dokan;

use Exception;
use WeDevs\Dokan\Admin\Status\Status;
use WeDevs\Dokan\Admin\Status\StatusElementFactory;

class VendorNavMenuChecker {

    /**
     * @since 4.0.0
     *
     * @var array $template_dependencies List of template dependencies.
     * [ 'route' => [ ['slug' => 'template-slug', 'name' => 'template-name' (Optional), 'args' = [] (Optional)  ] ] ]
     */
    protected array $template_dependencies = [
        'withdraw' => [
            [ 'slug' => 'withdraw/withdraw-dashboard' ],
            [ 'slug' => 'withdraw/withdraw' ],
            [ 'slug' => 'withdraw/header' ],
            [ 'slug' => 'withdraw/status-listing' ],
            [ 'slug' => 'withdraw/pending-request-listing' ],
            [ 'slug' => 'withdraw/approved-request-listing' ],
            [ 'slug' => 'withdraw/cancelled-request-listing' ],
            [ 'slug' => 'withdraw/tmpl-withdraw-request-popup' ],
            [ 'slug' => 'withdraw/request-form' ],
            [ 'slug' => 'withdraw/pending-request-listing-dashboard' ],
        ],
    ];


    /**
     * Forcefully resolved dependencies.
     *
     * Using `dokan_is_dashboard_nav_dependency_resolved` filter hook.
     *
     * @since 4.0.0
     *
     * @var array $forcefully_resolved_dependencies List of forcefully resolved dependencies.
     */
    protected array $forcefully_resolved_dependencies = [];

    /**
     * Constructor.
     */

    public function __construct() {
        add_filter( 'dokan_get_dashboard_nav', [ $this, 'convert_to_react_menu' ], 999 );
        add_filter( 'dokan_get_navigation_url', [ $this, 'maybe_rewrite_to_react_route' ], 5, 3 );
        add_filter( 'dokan_admin_notices', [ $this, 'display_notice' ] );
        add_action( 'dokan_status_after_describing_elements', [ $this, 'add_status_section' ] );
    }

    /**
     * Get template dependencies.
     *
     * @since 4.0.0
     *
     * @return array
     */
    public function get_template_dependencies(): array {
        return apply_filters( 'dokan_get_dashboard_nav_template_dependency', $this->template_dependencies );
    }

    /**
     * Convert menu items to react menu items
     *
     * @since 4.0.0
     *
     * @param array $menu_items Menu items.
     *
     * @return array
     */

    public function convert_to_react_menu( array $menu_items ): array {
        return array_map(
            function ( $item ) {
                if ( ! empty( $item['react_route'] ) && $this->is_dependency_resolved( $item['react_route'] ) ) {
                    $item['url'] = $this->get_url_for_route( $item['react_route'] );
                }
                if ( isset( $item['submenu'] ) ) {
                    $item['submenu'] = $this->convert_to_react_menu( $item['submenu'] );
                }

                return $item;
            }, $menu_items
        );
    }

    /**
     * Rewrite URL to React route if applicable.
     *
     * @since 4.0.8
     *
     * @param string $url URL.
     * @param string $name Name.
     * @param bool $new_url New URL.
     *
     * @return string
     */

    public function maybe_rewrite_to_react_route( string $url, $name, $new_url ): string {
        $name = (string) $name;
        if ( $name === '' || $name === 'new' ) {
            return $url;
        }
        if ( $new_url ) {
            return $url;
        }
        if ( strpos( $url, '#' ) !== false ) {
            return $url;
        }

        remove_filter( 'dokan_get_navigation_url', [ $this, 'maybe_rewrite_to_react_route' ], 5 );
            // Check if the top level menu exists and has a react route
        $menus = dokan_get_dashboard_nav();

		foreach ( $menus as $menu ) {
			$react_route = $menu['react_route'] ?? '';
			if ( $react_route === $name ) {
				$url = $menu['url'];
			}

			if ( isset( $menu['submenu'] ) && is_array( $menu['submenu'] ) ) {
				foreach ( $menu['submenu'] as $submenu ) {
					$react_route = $submenu['react_route'] ?? '';
					if ( $react_route === $name ) {
						$url = $submenu['url'];
					}
				}
			}
		}

		add_filter( 'dokan_get_navigation_url', [ $this, 'maybe_rewrite_to_react_route' ], 5, 3 );

        return $url;
    }

    /**
     * Check if the dependency is cleared or not.
     *
     * @since 4.0.0
     *
     * @param string $route Route.
     *
     * @return bool
     */
    protected function is_dependency_resolved( string $route ): bool {
        $clear        = true;
        $dependencies = $this->get_template_dependencies_resolutions();

        if ( ! empty( $dependencies[ trim( $route, '/' ) ] ) ) {
            $clear = false;
        }

        $filtered_clear = apply_filters( 'dokan_is_dashboard_nav_dependency_resolved', $clear, $route );

        if ( $clear !== $filtered_clear ) {
            $this->forcefully_resolved_dependencies[ $route ] = $filtered_clear;
        }

        return $filtered_clear;
    }

    /**
     * List forcefully resolved dependencies.
     *
     * @since 4.0.0
     *
     * @return array
     */
    public function list_force_dependency_resolved_alteration(): array {
        // Forcefully rebuild dependencies resolutions.
        dokan_get_dashboard_nav();

        return $this->forcefully_resolved_dependencies;
    }

    /**
     * Get URL for the route.
     *
     * @since 4.0.0
     *
     * @param string $route Route.
     *
     * @return string
     */
    protected function get_url_for_route( string $route ): string {
        $route = apply_filters( 'dokan_get_url_for_react_route', $route );

        return dokan_get_navigation_url( 'new' ) . '#' . trim( $route, '/' );
    }

    /**
     * Get template dependencies resolutions.
     *
     * @since 4.0.0
     *
     * @return array
     */
    protected function get_template_dependencies_resolutions(): array {
        $dependencies = $this->get_template_dependencies();

        $resolved_dependencies = array_map(
            fn( $dependency_array ): array => array_filter(
                array_map(
                    fn( $dependency ) => $this->get_overridden_template(
                        $dependency['slug'],
                        $dependency['name'] ?? '',
                        $dependency['args'] ?? []
                    ),
                    $dependency_array
                )
            ),
            $dependencies
        );

        return apply_filters( 'dokan_get_dashboard_nav_template_dependency_resolutions', $resolved_dependencies );
    }

    /**
     * Get overridden template part path.
     *
     * @since 4.0.0
     *
     * @param string $slug Template slug.
     * @param string $name Template name.
     * @param array $args Arguments.
     *
     * @return false|string Returns the template file if found otherwise false.
     */
    protected function get_overridden_template( string $slug, string $name = '', array $args = [] ) {
        $defaults         = [ 'pro' => false ];
        $args             = wp_parse_args( $args, $defaults );
        $template         = '';
        $default_template = '';

        // Look in yourtheme/dokan/slug-name.php and yourtheme/dokan/slug.php
        $template_path = ! empty( $name ) ? "{$slug}-{$name}.php" : "{$slug}.php";
        $template      = locate_template( [ dokan()->template_path() . $template_path ] );

        /**
         * Change template directory path filter
         *
         * @since 2.5.3
         */
        $template_path = apply_filters( 'dokan_set_template_path', dokan()->plugin_path() . '/templates', $template, $args );

        // Get default slug-name.php
        if ( ! $template && $name && file_exists( $template_path . "/{$slug}-{$name}.php" ) ) {
            $template         = $template_path . "/{$slug}-{$name}.php";
            $default_template = $template;
        }

        if ( ! $template && ! $name && file_exists( $template_path . "/{$slug}.php" ) ) {
            $template         = $template_path . "/{$slug}.php";
            $default_template = $template;
        }

        // Allow 3rd party plugin filter template file from their plugin
        $template = apply_filters( 'dokan_get_template_part', $template, $slug, $name );

        return $template && $default_template !== $template ? $template : false;
    }

    /**
     * List overridden templates.
     *
     * @since 4.0.0
     *
     * @return array
     */
    public function list_overridden_templates(): array {
        $dependencies = $this->get_template_dependencies_resolutions();
        $overridden_templates = [];
        foreach ( $dependencies as $dependency ) {
            $overridden_templates = array_merge( $overridden_templates, $dependency );
        }

        return $overridden_templates;
    }

    /**
     * Display notice if templates are overridden.
     *
     * @since 4.0.0
     *
     * @param array $notices Notices.
     *
     * @return array
     */
    public function display_notice( array $notices ): array {
        $overridden_templates = $this->list_overridden_templates();
        $overridden_routes = $this->list_force_dependency_resolved_alteration();

        if ( empty( $overridden_templates ) && empty( $overridden_routes ) ) {
            return $notices;
        }

        $notices[] = [
            'type'        => 'alert',
            'scope'       => 'global',
            'title'       => esc_html__( 'Some of Dokan Templates or functionalities are overridden which limit new features.', 'dokan-lite' ),
            'description' => esc_html__( 'Some of the Dokan templates or routes are overridden, which can prevent new features and intended functionalities from working correctly.', 'dokan-lite' ),
            'actions'     => [
                [
                    'type'   => 'primary',
                    'text' => esc_html__( 'Learn More', 'dokan-lite' ),
                    'action'   => admin_url( 'admin.php?page=dokan-dashboard#/status' ),
                    'target' => '_blank',
                ],
            ],
        ];

        return $notices;
    }

    /**
     * Add template dependencies to status page.
     *
     * @since 4.0.0
     *
     * @return void
     * @throws Exception
     */
    public function add_status_section( Status $status ) {
        $overridden_templates = $this->list_overridden_templates();
        $overridden_routes = $this->list_force_dependency_resolved_alteration();

        if ( empty( $overridden_templates ) && empty( $overridden_routes ) ) {
            return;
        }

        if ( ! empty( $overridden_templates ) ) {
            $template_table = StatusElementFactory::table( 'override_templates_table' )
                ->set_title( __( 'Overridden Template Table', 'dokan-lite' ) )
                ->set_headers(
                    [
                        __( 'Template', 'dokan-lite' ),
                    ]
                );

            foreach ( $overridden_templates as $id => $template ) {
                $template_table->add(
                    StatusElementFactory::table_row( 'override_row_' . $id )
                        ->add(
                            StatusElementFactory::table_column( 'template_' . $id )
                                ->add(
                                    StatusElementFactory::paragraph( 'file_location_' . $id )
                                        ->set_title( '<code>' . $template . '</code>' )
                                )
                                ->add(
                                    StatusElementFactory::paragraph( 'file_location_' . $id . '_instruction' )
                                        ->set_title( __( 'Please Remove the above file to enable new features.', 'dokan-lite' ) )
                                )
                        )
                );
            }
        }

        if ( ! empty( $overridden_routes ) ) {
            $route_table = StatusElementFactory::table( 'override_features_table' )
                ->set_title( __( 'Overridden Template Table', 'dokan-lite' ) )
                ->set_headers(
                    [
                        __( 'Route', 'dokan-lite' ),
                        __( 'Override Status', 'dokan-lite' ),
                    ]
                );

            foreach ( $overridden_routes as $route => $clearance ) {
                $route_table->add(
                    StatusElementFactory::table_row( 'override_feature_row_' . $route )
                        ->add(
                            StatusElementFactory::table_column( 'route_coll_' . $route )
                                ->add(
                                    StatusElementFactory::paragraph( 'route_' . $route )
                                        ->set_title( '<code>' . $route . '</code>' )
                                )
                        )
                        ->add(
                            StatusElementFactory::table_column( 'status_coll_' . $route )
                                ->add(
                                    StatusElementFactory::paragraph( 'status_' . $route )
                                        ->set_title( $clearance ? __( 'Forcefully enabled new feature.', 'dokan-lite' ) : __( 'Forcefully disabled new feature.', 'dokan-lite' ) )
                                )
                        )
                );
            }
        }

        $section = StatusElementFactory::section( 'overridden_features' )
            ->set_title( __( 'Overridden Templates or Routes', 'dokan-lite' ) )
            ->set_description( __( 'The listed templates or vendor dashboard routes are currently overridden, which are preventing enabling new features.', 'dokan-lite' ) );

        if ( ! empty( $overridden_templates ) ) {
            $section->add( $template_table );
        }

        if ( ! empty( $overridden_routes ) ) {
            $section->add( $route_table );
        }

        $status->add(
            $section
        );
    }
}
