<?php
/**
 * Admin controller: menus, assets and page routing.
 *
 * @package Lucrativeit_Subscription_Recurring_Billing
 */

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

/**
 * Registers the admin experience.
 */
class LUCRSURE_Admin {

	/**
	 * Settings instance.
	 *
	 * @var LUCRSURE_Settings
	 */
	protected $settings;

	/**
	 * Menu slug => module key map.
	 *
	 * @var array<string,string>
	 */
	protected $pages = array();

	/**
	 * External pages registered by add-ons via the `lucrsure_admin_pages` filter.
	 *
	 * Keyed by module slug; each value is an array with `label`, optional
	 * `capability` and a `view` (absolute path to the view file).
	 *
	 * @var array<string,array>
	 */
	protected $external_pages = array();

	/**
	 * Constructor.
	 *
	 * @param LUCRSURE_Settings $settings Settings.
	 */
	public function __construct( LUCRSURE_Settings $settings ) {
		$this->settings = $settings;
	}

	/**
	 * Register hooks.
	 */
	public function init() {
		add_action( 'admin_menu', array( $this, 'register_menu' ) );
		add_action( 'admin_init', array( $this, 'maybe_redirect_to_setup' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
	}

	/**
	 * Register the top-level menu and submenus.
	 */
	public function register_menu() {
		$cap = lucrsure_admin_capability();

		add_menu_page(
			lucrsure_plugin_name(),
			lucrsure_plugin_menu_label(),
			$cap,
			LUCRSURE_PLUGIN_SLUG,
			array( $this, 'render_dashboard' ),
			'dashicons-money-alt',
			30
		);

		$submenus = array(
			LUCRSURE_PLUGIN_SLUG => array( __( 'Dashboard', 'lucrativeit-subscription-recurring-billing' ), 'render_dashboard' ),
			'lucrsure-customers'                 => array( __( 'Customers', 'lucrativeit-subscription-recurring-billing' ), 'render_customers' ),
			'lucrsure-branches'                  => array( __( 'Branches', 'lucrativeit-subscription-recurring-billing' ), 'render_branches' ),
			'lucrsure-plan-categories'           => array( __( 'Plan Categories', 'lucrativeit-subscription-recurring-billing' ), 'render_plan_categories' ),
			'lucrsure-plans'                     => array( __( 'Plans', 'lucrativeit-subscription-recurring-billing' ), 'render_plans' ),
			'lucrsure-subscriptions'             => array( __( 'Subscriptions', 'lucrativeit-subscription-recurring-billing' ), 'render_subscriptions' ),
			'lucrsure-billing'                   => array( __( 'Billing', 'lucrativeit-subscription-recurring-billing' ), 'render_billing' ),
			'lucrsure-reports'                   => array( __( 'Reports', 'lucrativeit-subscription-recurring-billing' ), 'render_reports' ),
			'lucrsure-settings'                  => array( __( 'Settings', 'lucrativeit-subscription-recurring-billing' ), 'render_settings' ),
		);

		foreach ( $submenus as $slug => $data ) {
			add_submenu_page(
				LUCRSURE_PLUGIN_SLUG,
				$data[0],
				$data[0],
				$cap,
				$slug,
				array( $this, $data[1] )
			);
		}

		/**
		 * Allow add-ons to register additional pages inside the plugin app shell.
		 *
		 * Each entry is keyed by a module slug and contains:
		 *   - label:      Menu/title label.
		 *   - view:       Absolute path to the view file to render.
		 *   - capability: (optional) Capability required; defaults to the plugin capability.
		 *
		 * The page is reachable at admin.php?page=lucrsure-{slug} and rendered inside
		 * the plugin layout (sidebar + header/footer).
		 *
		 * @param array $pages External pages keyed by module slug.
		 */
		$this->external_pages = (array) apply_filters( 'lucrsure_admin_pages', array() );

		foreach ( $this->external_pages as $module => $page ) {
			$label    = isset( $page['label'] ) ? $page['label'] : ucfirst( $module );
			$page_cap = isset( $page['capability'] ) ? $page['capability'] : $cap;

			add_submenu_page(
				LUCRSURE_PLUGIN_SLUG,
				$label,
				$label,
				$page_cap,
				'lucrsure-' . $module,
				array( $this, 'render_external_page' )
			);
		}

		add_submenu_page(
			null,
			__( 'Setup', 'lucrativeit-subscription-recurring-billing' ),
			__( 'Setup', 'lucrativeit-subscription-recurring-billing' ),
			$cap,
			'lucrsure-setup',
			array( $this, 'render_setup' )
		);
	}

	/**
	 * Redirect to the setup wizard after activation or while onboarding is pending.
	 */
	public function maybe_redirect_to_setup() {
		if ( wp_doing_ajax() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
			return;
		}

		if ( ! current_user_can( lucrsure_admin_capability() ) ) {
			return;
		}

		if ( lucrsure_is_setup_screen() ) {
			delete_option( 'lucrsure_activation_redirect' );
			return;
		}

		$activation_redirect = (bool) get_option( 'lucrsure_activation_redirect' );
		$needs_setup         = lucrsure_should_show_onboarding();

		if ( ! $activation_redirect && ! $needs_setup ) {
			return;
		}

		if ( ! $needs_setup ) {
			delete_option( 'lucrsure_activation_redirect' );
			return;
		}

		$should_redirect = $activation_redirect;
		if ( ! $should_redirect && $this->is_plugin_screen() ) {
			$should_redirect = true;
		}

		if ( ! $should_redirect ) {
			return;
		}

		// Bulk plugin activation skips the wizard redirect.
		if ( isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
			delete_option( 'lucrsure_activation_redirect' );
			return;
		}

		delete_option( 'lucrsure_activation_redirect' );
		wp_safe_redirect( lucrsure_admin_url( 'setup' ) );
		exit;
	}

	/**
	 * Whether the current admin screen belongs to this plugin.
	 *
	 * Prefer `get_current_screen()` so we do not read unsanitized request
	 * input for routing. Falls back to a capability-gated page check only
	 * when the screen object is not available yet (early admin_init).
	 *
	 * @return bool
	 */
	protected function is_plugin_screen() {
		if ( ! is_admin() || ! current_user_can( lucrsure_admin_capability() ) ) {
			return false;
		}

		// Page query is the most reliable signal for our registered screens,
		// including the hidden setup page (null parent → admin_page_lucrsure-setup).
		if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen detection.
			$page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen detection.
			if ( LUCRSURE_PLUGIN_SLUG === $page || 0 === strpos( $page, 'lucrsure-' ) ) {
				return true;
			}
		}

		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( $screen && ! empty( $screen->id ) ) {
			return false !== strpos( $screen->id, LUCRSURE_PLUGIN_SLUG )
				|| false !== strpos( $screen->id, 'lucrsure-' );
		}

		return false;
	}

	/**
	 * Enqueue admin CSS/JS via WordPress asset APIs.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_assets( $hook ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
		// Hide WP submenu items on all admin screens (pages stay registered;
		// nav is via the plugin sidebar). Inline-only handle — no file URL.
		wp_register_style( 'lucrsure-admin-global', false, array(), LUCRSURE_VERSION );
		wp_enqueue_style( 'lucrsure-admin-global' );
		wp_add_inline_style(
			'lucrsure-admin-global',
			'#toplevel_page_' . esc_attr( LUCRSURE_PLUGIN_SLUG ) . ' .wp-submenu { display: none !important; }'
		);

		if ( ! $this->is_plugin_screen() ) {
			return;
		}

		wp_enqueue_style(
			'lucrsure-admin',
			LUCRSURE_PLUGIN_URL . 'admin/css/lucrsure-admin.css',
			array(),
			LUCRSURE_VERSION
		);

		wp_add_inline_style( 'lucrsure-admin', $this->get_immersive_css() );

		wp_enqueue_script(
			'lucrsure-admin',
			LUCRSURE_PLUGIN_URL . 'admin/js/lucrsure-admin.js',
			array( 'jquery' ),
			LUCRSURE_VERSION,
			true
		);

		wp_localize_script(
			'lucrsure-admin',
			'LUCRSURE',
			array(
				'ajaxUrl' => admin_url( 'admin-ajax.php' ),
				'nonce'   => wp_create_nonce( 'lucrsure_admin' ),
				'i18n'    => array(
					'selectLogo'      => __( 'Select Logo', 'lucrativeit-subscription-recurring-billing' ),
					'useLogo'         => __( 'Use Logo', 'lucrativeit-subscription-recurring-billing' ),
					'noLogo'          => __( 'No logo selected', 'lucrativeit-subscription-recurring-billing' ),
					'selectThumbnail' => __( 'Select Thumbnail', 'lucrativeit-subscription-recurring-billing' ),
					'useThumbnail'    => __( 'Use Image', 'lucrativeit-subscription-recurring-billing' ),
					'noThumbnail'     => __( 'No thumbnail selected', 'lucrativeit-subscription-recurring-billing' ),
					'selectImage'     => __( 'Select Branch Image', 'lucrativeit-subscription-recurring-billing' ),
					'selectHeroImage' => __( 'Select Hero Image', 'lucrativeit-subscription-recurring-billing' ),
					'newFaqItem'      => __( 'New FAQ Item', 'lucrativeit-subscription-recurring-billing' ),
					/* translators: %d: FAQ item number */
					'faqItem'         => __( 'FAQ Item %d', 'lucrativeit-subscription-recurring-billing' ),
					'useImage'        => __( 'Use Image', 'lucrativeit-subscription-recurring-billing' ),
					'noImage'         => __( 'No image selected', 'lucrativeit-subscription-recurring-billing' ),
					'importStarting'  => __( 'Starting import…', 'lucrativeit-subscription-recurring-billing' ),
					'importFailed'    => __( 'Import failed. Please try again.', 'lucrativeit-subscription-recurring-billing' ),
					'importComplete'  => __( 'Import complete! Reloading dashboard…', 'lucrativeit-subscription-recurring-billing' ),
					'selectCategory'  => __( 'Please select at least one category to import.', 'lucrativeit-subscription-recurring-billing' ),
					'setupDismissed'  => __( 'Setup skipped. You can add your own data anytime.', 'lucrativeit-subscription-recurring-billing' ),
				),
				'setup'   => array(
					'isPage' => lucrsure_is_setup_screen(),
				),
				'dashboardUrl' => lucrsure_admin_url( 'dashboard' ),
			)
		);

		$hook = (string) $hook;
		if ( false !== strpos( $hook, 'lucrsure-settings' )
			|| false !== strpos( $hook, 'lucrsure-plans' )
			|| false !== strpos( $hook, 'lucrsure-branches' )
		) {
			wp_enqueue_media();
		}
	}

	/**
	 * Layout CSS so the plugin renders cleanly inside wp-admin while keeping
	 * the standard WordPress admin menu (and admin bar) on the left.
	 *
	 * @return string
	 */
	protected function get_immersive_css() {
		if ( lucrsure_is_setup_screen() ) {
			return '
				#wpcontent { padding-left: 16px !important; }
				#wpbody-content { padding-bottom: 0 !important; }
				#wpfooter { display: none !important; }
				.wrap.lucrsure-setup-screen { margin: 16px 16px 16px 0; }
				.lucrsure-setup-screen .notice, .lucrsure-setup-screen .update-nag { display: none; }
			';
		}

		return '
			#wpcontent { padding-left: 16px !important; }
			#wpbody-content { padding-bottom: 0 !important; }
			#wpfooter { display: none !important; }
			.lucrsure-app { min-height: calc(100vh - 32px); margin: 16px 16px 16px 0; border-radius: 14px; overflow: hidden; box-shadow: 0 1px 3px rgba(16,24,40,.08); align-items: stretch; }
			.lucrsure-app .lucrsure-sidebar { min-height: calc(100vh - 64px); }
			.lucrsure-app .notice, .lucrsure-app .update-nag { display: none; }
			@media (max-width: 782px) {
				.lucrsure-app { min-height: calc(100vh - 46px); }
				.lucrsure-app .lucrsure-sidebar { min-height: calc(100vh - 78px); }
			}
		';
	}

	/**
	 * Render an add-on page registered via `lucrsure_admin_pages`.
	 *
	 * Resolves the module slug from the current `page` query arg
	 * (e.g. lucrsure-staff → staff).
	 */
	public function render_external_page() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin routing.
		$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
		if ( 0 !== strpos( $page, 'lucrsure-' ) ) {
			wp_die( esc_html__( 'Page not found.', 'lucrativeit-subscription-recurring-billing' ) );
		}

		$module = substr( $page, strlen( 'lucrsure-' ) );
		if ( '' === $module || ! isset( $this->external_pages[ $module ] ) ) {
			wp_die( esc_html__( 'Page not found.', 'lucrativeit-subscription-recurring-billing' ) );
		}

		$this->render( $module );
	}

	/**
	 * Render a module view inside the app shell.
	 *
	 * @param string $module Module slug.
	 */
	protected function render( $module ) {
		$settings = $this->settings;
		$active   = $module;
		$modules  = lucrsure_get_modules();

		// Resolve the view path up-front so it cannot be affected by variables
		// defined inside the including layout/sidebar templates.
		$view_file = LUCRSURE_PLUGIN_DIR . 'admin/views/' . $module . '.php';

		// Allow add-on (external) pages to supply their own view / form files.
		if ( isset( $this->external_pages[ $module ] ) && is_array( $this->external_pages[ $module ] ) ) {
			$external = $this->external_pages[ $module ];
			if ( $this->is_form() && ! empty( $external['form_view'] ) ) {
				$candidate = $this->resolve_safe_view_path( $external['form_view'] );
				if ( $candidate ) {
					$view_file = $candidate;
				}
			} elseif ( ! empty( $external['view'] ) ) {
				$candidate = $this->resolve_safe_view_path( $external['view'] );
				if ( $candidate ) {
					$view_file = $candidate;
				}
			}
		}

		// Opens .lucrsure-app, renders the sidebar, opens .lucrsure-content + topbar + .lucrsure-main.
		include LUCRSURE_PLUGIN_DIR . 'admin/views/layout/header.php';

		$this->render_flash();

		if ( file_exists( $view_file ) ) {
			include $view_file;
		} else {
			echo '<p>' . esc_html__( 'View not found.', 'lucrativeit-subscription-recurring-billing' ) . '</p>';
		}

		// Closes .lucrsure-main, footer, .lucrsure-content, .lucrsure-app.
		include LUCRSURE_PLUGIN_DIR . 'admin/views/layout/footer.php';
	}

	/**
	 * Resolve an add-on view path and ensure it lives under an allowed plugin directory.
	 *
	 * @param string $path Absolute path claimed by an add-on.
	 * @return string|null Real path when safe, otherwise null.
	 */
	protected function resolve_safe_view_path( $path ) {
		$path = wp_normalize_path( (string) $path );
		if ( '' === $path || ! file_exists( $path ) ) {
			return null;
		}

		$real = realpath( $path );
		if ( false === $real ) {
			return null;
		}

		$real = wp_normalize_path( $real );
		$allowed_roots = array(
			wp_normalize_path( LUCRSURE_PLUGIN_DIR ),
		);

		if ( defined( 'LSPP_PLUGIN_DIR' ) && LSPP_PLUGIN_DIR ) {
			$allowed_roots[] = wp_normalize_path( LSPP_PLUGIN_DIR );
		}

		foreach ( $allowed_roots as $root ) {
			$root = trailingslashit( $root );
			if ( 0 === strpos( $real, $root ) ) {
				return $real;
			}
		}

		return null;
	}

	/**
	 * Append body class while the setup modal is active.
	 *
	 * @param string $classes Space-separated admin body classes.
	 * @return string
	 */
	public function admin_body_class( $classes ) {
		if ( lucrsure_is_setup_screen() ) {
			$classes .= ' lucrsure-setup-screen';
		}
		return $classes;
	}

	/**
	 * First-run setup wizard (hidden admin page).
	 */
	public function render_setup() {
		if ( ! lucrsure_should_show_onboarding() ) {
			wp_safe_redirect( lucrsure_admin_url( 'dashboard' ) );
			exit;
		}

		echo '<div class="wrap lucrsure-setup-screen">';
		include LUCRSURE_PLUGIN_DIR . 'admin/views/setup.php';
		echo '</div>';
	}

	/**
	 * Output a flash notice stored after a guarded admin-post redirect.
	 */
	protected function render_flash() {
		if ( ! current_user_can( lucrsure_admin_capability() ) ) {
			return;
		}

		$transient = 'lucrsure_admin_flash_' . get_current_user_id();
		$code      = get_transient( $transient );
		if ( ! $code ) {
			return;
		}
		delete_transient( $transient );
		$code = sanitize_key( $code );

		$map = array(
			'saved'                 => array( __( 'Settings saved successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'created'               => array( __( 'Record created successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'updated'               => array( __( 'Record updated successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'deleted'               => array( __( 'Record deleted.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'branch_created'        => array( __( 'Branch created successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'plan_created'          => array( __( 'Plan created successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'category_created'      => array( __( 'Plan category created successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'gateways_saved'        => array( __( 'Payment Gateways settings saved successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'email_sent'            => array( __( 'Test email sent successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'email_failed'          => array( __( 'Test email could not be sent. Check your SMTP settings and try again.', 'lucrativeit-subscription-recurring-billing' ), 'error' ),
			'email_invalid'         => array( __( 'Please enter a valid email address.', 'lucrativeit-subscription-recurring-billing' ), 'error' ),
			'invoice_paid'          => array( __( 'Invoice marked as paid.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'invoice_paid_notified' => array( __( 'Invoice marked as paid and payment confirmation emailed to the customer.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'demo_imported'         => array( __( 'Sample data and public plan pages imported successfully.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'demo_import_blocked'   => array( __( 'Sample data could not be imported because records already exist.', 'lucrativeit-subscription-recurring-billing' ), 'warning' ),
			'onboarding_dismissed'  => array( __( 'Getting started guide dismissed. You can add your own data anytime.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'plan_pages_synced'     => array( __( 'Public plan pages created or updated for each category.', 'lucrativeit-subscription-recurring-billing' ), 'success' ),
			'error'                 => array( __( 'Something went wrong. Please try again.', 'lucrativeit-subscription-recurring-billing' ), 'error' ),
		);

		if ( ! isset( $map[ $code ] ) ) {
			return;
		}

		$message = $map[ $code ][0];
		$type    = $map[ $code ][1];

		if ( 'demo_imported' === $code ) {
			$hub_url = LUCRSURE_Plan_Pages::get_hub_url();
			if ( $hub_url ) {
				$message .= ' <a href="' . esc_url( $hub_url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'View public plans hub', 'lucrativeit-subscription-recurring-billing' ) . '</a>';
			}
			lucrsure_render_notice( $message, $type, true );
			return;
		}

		lucrsure_render_notice( $message, $type );
	}

	/* --- Page callbacks --- */

	/**
	 * Dashboard page.
	 */
	public function render_dashboard() {
		$this->render( 'dashboard' );
	}

	/**
	 * Customers page (list or form).
	 */
	public function render_customers() {
		$this->render( $this->is_form() ? 'customer-form' : 'customers' );
	}

	/**
	 * Branches page.
	 */
	public function render_branches() {
		$this->render( $this->is_form() ? 'branch-form' : 'branches' );
	}

	/**
	 * Subscriptions page.
	 */
	public function render_subscriptions() {
		$this->render( $this->is_form() ? 'subscription-form' : 'subscriptions' );
	}

	/**
	 * Plans page.
	 */
	public function render_plans() {
		$this->render( $this->is_form() ? 'plan-form' : 'plans' );
	}

	/**
	 * Plan categories page.
	 */
	public function render_plan_categories() {
		$this->render( $this->is_form() ? 'plan-category-form' : 'plan-categories' );
	}

	/**
	 * Billing page.
	 */
	public function render_billing() {
		if ( ! current_user_can( lucrsure_admin_capability() ) ) {
			wp_die( esc_html__( 'You are not allowed to access this page.', 'lucrativeit-subscription-recurring-billing' ) );
		}

		$action = '';
		$id     = 0;

		if ( isset( $_GET['_wpnonce'] )
			&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'lucrsure_admin_form' )
		) {
			$action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : '';
			$id     = isset( $_GET['id'] ) ? absint( wp_unslash( $_GET['id'] ) ) : 0;
		}

		if ( 'new' === $action ) {
			$this->render( 'invoice-form' );
			return;
		}

		if ( in_array( $action, array( 'view', 'edit' ), true ) && $id > 0 ) {
			$this->render( 'invoice-detail' );
			return;
		}

		$this->render( 'billing' );
	}

	/**
	 * Reports page.
	 */
	public function render_reports() {
		$this->render( 'reports' );
	}

	/**
	 * Settings page.
	 */
	public function render_settings() {
		$this->render( 'settings' );
	}

	/**
	 * Whether the current request is a create/edit form.
	 *
	 * Requires capability + a valid `lucrsure_admin_form` nonce so action/id
	 * query args cannot be forged without authorization.
	 *
	 * @return bool
	 */
	protected function is_form() {
		if ( ! current_user_can( lucrsure_admin_capability() ) ) {
			return false;
		}

		if ( ! isset( $_GET['action'], $_GET['_wpnonce'] ) ) {
			return false;
		}

		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'lucrsure_admin_form' ) ) {
			return false;
		}

		$action = sanitize_key( wp_unslash( $_GET['action'] ) );

		return in_array( $action, array( 'new', 'edit' ), true );
	}
}
