<?php
/**
 * Dashboard view: summary header, scan controls, the three audit tabs
 * (Search Appearance / Social Appearance / Issues), issue-details modal.
 *
 * View body is wrapped in a render function to keep locals out of the
 * includer's scope (Plugin Check NonPrefixedVariableFound).
 *
 * @package search-social-appearance-audit
 */

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

function ssaa_render_dashboard_page() {
	$summary = SSAA_Results::summary();
	$state   = SSAA_Scan::state();

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only view state.
	$tab  = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'search';
	$tab  = in_array( $tab, array( 'social', 'search', 'issues', 'ignored' ), true ) ? $tab : 'search';
	$base = admin_url( 'admin.php?page=' . SSAA_Admin::PAGE_SLUG );

	echo '<div class="wrap ssaa-wrap">';
	SSAA_Plugin::render_page_header( __( 'PlugUpp Search & Social Appearance Audit', 'search-social-appearance-audit' ), 'dashboard' );

	// --- Action notices --------------------------------------------------------
	// phpcs:disable WordPress.Security.NonceVerification.Recommended -- display-only flags set by our own redirects.
	if ( isset( $_GET['ssaa_excluded'] ) ) {
		$n = absint( wp_unslash( $_GET['ssaa_excluded'] ) );
		echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( sprintf(
			/* translators: %d: number of items */
			_n( '%d item excluded from the audit.', '%d items excluded from the audit.', $n, 'search-social-appearance-audit' ),
			$n
		) ) . '</p></div>';
	}
	if ( isset( $_GET['ssaa_included'] ) ) {
		$n = absint( wp_unslash( $_GET['ssaa_included'] ) );
		echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( sprintf(
			/* translators: %d: number of items */
			_n( '%d item re-included. It will reappear after the next scan.', '%d items re-included. They will reappear after the next scan.', $n, 'search-social-appearance-audit' ),
			$n
		) ) . '</p></div>';
	}
	if ( isset( $_GET['ssaa_unignored'] ) ) {
		echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Issue un-ignored. Counts have been updated.', 'search-social-appearance-audit' ) . '</p></div>';
	}
	// phpcs:enable WordPress.Security.NonceVerification.Recommended

	// --- Summary header ------------------------------------------------------
	// Findings are split by severity (Issues = critical only), matching the
	// per-row badges and the Findings tab. The three severity boxes are filled
	// soft tints so the severity shape reads at a glance, always shown. A box
	// whose count is ZERO drops its severity class below and renders neutral -
	// colour means "there is something here", never a coloured-but-empty alarm.
	// See DECISIONS.md "Severity is first-class".
	echo '<div class="ssaa-summary">';
	$boxes = array(
		array( __( 'Items scanned', 'search-social-appearance-audit' ), (string) $summary['total'], '' ),
		array( __( 'Issues', 'search-social-appearance-audit' ), (string) $summary['critical_issues'], 'ssaa-summary-critical' ),
		array( __( 'Warnings', 'search-social-appearance-audit' ), (string) $summary['warning_issues'], 'ssaa-summary-warning' ),
		array( __( 'Notices', 'search-social-appearance-audit' ), (string) $summary['notice_issues'], 'ssaa-summary-notice' ),
		array( __( 'Scan errors', 'search-social-appearance-audit' ), (string) $summary['errors'], '' ),
		array( __( 'Last scan (UTC)', 'search-social-appearance-audit' ), ( '' !== $summary['last_scan'] ) ? $summary['last_scan'] : __( 'Never', 'search-social-appearance-audit' ), '' ),
	);
	foreach ( $boxes as $box ) {
		list( $label, $value, $box_class ) = $box;
		// Zero-muting: a severity box with a count of 0 renders neutral.
		if ( '' !== $box_class && 0 === (int) $value ) {
			$box_class = '';
		}
		echo '<div class="ssaa-summary-box ' . esc_attr( $box_class ) . '"><span class="ssaa-summary-value">' . esc_html( $value ) . '</span><span class="ssaa-summary-label">' . esc_html( $label ) . '</span></div>';
	}
	echo '</div>';

	// --- Scan controls ---------------------------------------------------------
	// Scanning runs entirely on this site (self-request render + local analysis)
	// and never requires a Freemius connection or any external service - the
	// free plugin is fully functional out of the box (WordPress.org Guideline 5).
	echo '<div class="ssaa-scan-controls">';
	echo '<button type="button" class="button button-primary" id="ssaa-start-scan"' . disabled( $state['running'], true, false ) . '>'
		. esc_html__( 'Scan now', 'search-social-appearance-audit' ) . '</button> ';
	echo '<button type="button" class="button" id="ssaa-cancel-scan"' . disabled( $state['running'], false, false ) . '>'
		. esc_html__( 'Cancel', 'search-social-appearance-audit' ) . '</button>';
	echo '<div id="ssaa-progress" class="ssaa-progress"' . ( $state['running'] ? '' : ' hidden' ) . '>';
	echo '<div class="ssaa-progress-track"><div class="ssaa-progress-fill" id="ssaa-progress-fill"></div></div>';
	echo '<span class="ssaa-progress-text" id="ssaa-progress-text"></span>';
	echo '</div>';
	echo '<p class="description">'
		. esc_html__( 'Scanning renders each page the way a visitor sees it and audits the metadata that actually ships. You can leave this page - the scan continues in the background.', 'search-social-appearance-audit' )
		. '</p>';
	echo '</div>';

	// --- Upgrade banner --------------------------------------------------------
	// Lives here on the Dashboard (the high-traffic screen, and the moment of
	// most context - the user has just seen their audit status), not on the
	// Settings page where the Premium tab already carries the upsell. Shown only
	// on the free build / unlicensed install; named headline features, single
	// CTA (describe, not demonstrate). See _standards CONVENTIONS upsell rules.
	$ssaa_upgrade_url = SSAA_License::upgrade_url();
	if ( ! SSAA_License::is_premium() && '' !== $ssaa_upgrade_url ) {
		echo '<div class="ssaa-upgrade-banner">';
		echo '<span class="ssaa-upgrade-banner__icon dashicons dashicons-star-filled" aria-hidden="true"></span>';
		echo '<div class="ssaa-upgrade-banner__content">';
		echo '<strong>' . esc_html__( 'Do more with Premium', 'search-social-appearance-audit' ) . '</strong>';
		echo '<span>' . esc_html__( 'Scheduled scans, email reports, CSV export, custom post types and WooCommerce, and more.', 'search-social-appearance-audit' ) . '</span>';
		echo '</div>';
		echo '<a class="button button-primary ssaa-upgrade-banner__button" href="' . esc_url( $ssaa_upgrade_url ) . '">'
			. esc_html__( 'Upgrade to Premium', 'search-social-appearance-audit' ) . '</a>';
		echo '</div>';
	}

	// --- Tabs ------------------------------------------------------------------
	$ignore_lists = SSAA_Ignores::get();
	$ignore_count = count( $ignore_lists['site'] );
	foreach ( $ignore_lists['posts'] as $ignored_codes ) {
		$ignore_count += count( $ignored_codes );
	}

	// Search first - it leads the plugin name and now also carries imagery
	// (the reason Social used to lead). See DECISIONS.md 2026-06-14.
	$tabs = array(
		'search'   => __( 'Search Appearance', 'search-social-appearance-audit' ),
		'social'   => __( 'Social Appearance', 'search-social-appearance-audit' ),
		'issues'   => __( 'Findings', 'search-social-appearance-audit' ),
		'ignored'  => __( 'Ignored', 'search-social-appearance-audit' ),
	);

	// The Findings tab carries three fixed severity badges (issues/warnings/
	// notices), always shown with a count even at zero, so the severity shape
	// reads at a glance and nothing jumps as counts change.
	$ssaa_findings_badges = '<span class="ssaa-tab-sev ssaa-tab-sev-critical">' . esc_html( (string) $summary['critical_issues'] ) . '</span>'
		. '<span class="ssaa-tab-sev ssaa-tab-sev-warning">' . esc_html( (string) $summary['warning_issues'] ) . '</span>'
		. '<span class="ssaa-tab-sev ssaa-tab-sev-notice">' . esc_html( (string) $summary['notice_issues'] ) . '</span>';

	echo '<nav class="nav-tab-wrapper ssaa-nav-tab-wrapper">';
	foreach ( $tabs as $key => $label ) {
		if ( 'ignored' === $key && 0 === $ignore_count && 'ignored' !== $tab ) {
			continue; // Same pattern: appears once something is ignored.
		}
		$class = 'nav-tab' . ( $tab === $key ? ' nav-tab-active' : '' );
		$url   = ( 'search' === $key ) ? $base : add_query_arg( 'tab', $key, $base );
		$count = '';
		if ( 'issues' === $key ) {
			$count = ' ' . $ssaa_findings_badges;
		}
		if ( 'ignored' === $key && $ignore_count > 0 ) {
			$count = ' <span class="ssaa-tab-count ssaa-tab-count-muted">' . esc_html( (string) $ignore_count ) . '</span>';
		}
		echo '<a class="' . esc_attr( $class ) . '" href="' . esc_url( $url ) . '">' . esc_html( $label ) . wp_kses_post( $count ) . '</a>';
	}
	SSAA_Plugin::render_docs_link( 'dashboard' );
	echo '</nav>';

	// --- Ignored view --------------------------------------------------------------
	if ( 'ignored' === $tab ) {
		ssaa_render_ignored_view( $ignore_lists, $base );
		SSAA_Plugin::render_admin_footer();
		echo '</div>'; // .wrap
		return;
	}

	// --- Results table with WordPress-standard filters -------------------------
	// Status is the get_views() subsubsub above the table (All | Published |
	// Drafts | Scheduled | Pending); type is the extra_tablenav() dropdown in the
	// table's top toolbar. Both are rendered by SSAA_Results_Table - replacing the
	// old hand-rolled type+status nav, so the axes are orthogonal and compose
	// (Drafts + Products = draft products). See docs/SPEC-standard-filters.md.
	$table = new SSAA_Results_Table( $tab );
	$table->prepare_items();

	// Status filter tabs (WP-standard) above the table. views() emits nothing
	// when there is no unpublished content (the free build), in which case the
	// clear is harmless. .ssaa-table-scroll is a BFC (overflow-x) and would tuck
	// beside the floated subsubsub without the clear.
	$table->views();
	echo '<div class="clear"></div>';

	/**
	 * Extension point: add-on files render their own controls between the
	 * filter links and the results table (e.g. additional filters).
	 *
	 * @param string $tab Current tab.
	 */
	do_action( 'ssaa_before_results_table', $tab );

	// The active status rides the results form as a hidden input so the type
	// dropdown's Filter button and the bulk-action submit (this is a method=get
	// form, exactly as core's edit.php runs its filter + bulk form) preserve it.
	// The type value is the live <select name="ssaa_type"> in the tablenav, so it
	// needs no hidden input.
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only view state.
	$current_status = isset( $_GET['ssaa_status'] ) ? sanitize_key( wp_unslash( $_GET['ssaa_status'] ) ) : '';

	echo '<form method="get">';
	echo '<input type="hidden" name="page" value="' . esc_attr( SSAA_Admin::PAGE_SLUG ) . '" />';
	echo '<input type="hidden" name="tab" value="' . esc_attr( $tab ) . '" />';
	if ( '' !== $current_status ) {
		echo '<input type="hidden" name="ssaa_status" value="' . esc_attr( $current_status ) . '" />';
	}
	echo '<div class="ssaa-table-scroll ssaa-table-scroll-' . esc_attr( $tab ) . '">';
	$table->display();
	echo '</div>';
	echo '</form>';

	// --- Issue details modal (filled by JS) -------------------------------------
	echo '<div id="ssaa-modal-overlay" class="ssaa-modal-overlay" hidden>';
	echo '<div class="ssaa-modal" role="dialog" aria-modal="true" aria-labelledby="ssaa-modal-title">';
	echo '<div class="ssaa-modal-head">';
	echo '<h2 id="ssaa-modal-title"></h2>';
	echo '<button type="button" class="button-link ssaa-modal-close" aria-label="' . esc_attr__( 'Close', 'search-social-appearance-audit' ) . '">&times;</button>';
	echo '</div>';
	echo '<div class="ssaa-modal-body" id="ssaa-modal-body"></div>';
	echo '<div class="ssaa-modal-foot">';
	echo '<a href="#" target="_blank" rel="noopener" class="button" id="ssaa-modal-view">' . esc_html__( 'View page', 'search-social-appearance-audit' ) . '</a> ';
	echo '<a href="#" class="button" id="ssaa-modal-edit">' . esc_html__( 'Edit page', 'search-social-appearance-audit' ) . '</a> ';
	echo '<button type="button" class="button button-primary" id="ssaa-modal-rescan">' . esc_html__( 'Re-scan', 'search-social-appearance-audit' ) . '</button>';
	echo '</div>';
	echo '</div>';
	echo '</div>';

	// --- Image lightbox (full-size preview image; filled by JS) ---------------
	echo '<div id="ssaa-img-lightbox" class="ssaa-img-lightbox" hidden>';
	echo '<button type="button" class="ssaa-img-lightbox-close" aria-label="' . esc_attr__( 'Close', 'search-social-appearance-audit' ) . '">&times;</button>';
	echo '<figure class="ssaa-lightbox-stage">';
	echo '<span class="ssaa-lightbox-imgwrap"><img id="ssaa-img-lightbox-img" src="" alt="" /><span class="ssaa-lightbox-frame" id="ssaa-img-lightbox-frame" hidden></span></span>';
	echo '<figcaption class="ssaa-lightbox-caption" id="ssaa-img-lightbox-caption" hidden></figcaption>';
	echo '</figure>';
	echo '</div>';

	SSAA_Plugin::render_admin_footer();
	echo '</div>';
}

/**
 * The Ignored view: sitewide and per-page ignore rules with un-ignore links.
 *
 * @param array  $lists Ignore lists (site + posts).
 * @param string $base  Dashboard base URL.
 */
function ssaa_render_ignored_view( array $lists, $base ) {
	if ( empty( $lists['site'] ) && empty( $lists['posts'] ) ) {
		echo '<p>' . esc_html__( 'No issues are ignored. Use the issue details popup to ignore an issue on one page or sitewide.', 'search-social-appearance-audit' ) . '</p>';
		return;
	}

	$tab_base = add_query_arg( 'tab', 'ignored', $base );

	echo '<p class="description">' . esc_html__( 'Ignored issues stay visible (greyed) in the details popup but do not count anywhere. Un-ignoring takes effect immediately.', 'search-social-appearance-audit' ) . '</p>';

	if ( ! empty( $lists['site'] ) ) {
		echo '<h2>' . esc_html__( 'Ignored sitewide', 'search-social-appearance-audit' ) . '</h2>';
		echo '<table class="widefat striped"><thead><tr>';
		echo '<th>' . esc_html__( 'Issue', 'search-social-appearance-audit' ) . '</th>';
		echo '<th>' . esc_html__( 'Actions', 'search-social-appearance-audit' ) . '</th>';
		echo '</tr></thead><tbody>';
		foreach ( $lists['site'] as $code ) {
			$url = wp_nonce_url(
				add_query_arg( array( 'ssaa_action' => 'unignore', 'scope' => 'site', 'code' => $code ), $tab_base ),
				'ssaa_unignore_' . $code
			);
			echo '<tr><td><code>' . esc_html( $code ) . '</code></td>';
			echo '<td><a href="' . esc_url( $url ) . '">' . esc_html__( 'Un-ignore', 'search-social-appearance-audit' ) . '</a></td></tr>';
		}
		echo '</tbody></table>';
	}

	if ( ! empty( $lists['posts'] ) ) {
		echo '<h2>' . esc_html__( 'Ignored on specific pages', 'search-social-appearance-audit' ) . '</h2>';
		echo '<table class="widefat striped"><thead><tr>';
		echo '<th>' . esc_html__( 'Title', 'search-social-appearance-audit' ) . '</th>';
		echo '<th>' . esc_html__( 'Issue', 'search-social-appearance-audit' ) . '</th>';
		echo '<th>' . esc_html__( 'Actions', 'search-social-appearance-audit' ) . '</th>';
		echo '</tr></thead><tbody>';
		foreach ( $lists['posts'] as $post_id => $codes ) {
			$title     = get_the_title( $post_id );
			$title     = ( '' !== $title ) ? $title : sprintf(
				/* translators: %d: post ID */
				__( '(ID %d)', 'search-social-appearance-audit' ),
				$post_id
			);
			$edit_link = get_edit_post_link( $post_id );
			foreach ( $codes as $code ) {
				$url = wp_nonce_url(
					add_query_arg( array( 'ssaa_action' => 'unignore', 'scope' => 'page', 'post' => $post_id, 'code' => $code ), $tab_base ),
					'ssaa_unignore_' . $code
				);
				echo '<tr>';
				echo '<td>' . ( $edit_link ? '<a href="' . esc_url( $edit_link ) . '">' . esc_html( $title ) . '</a>' : esc_html( $title ) ) . '</td>';
				echo '<td><code>' . esc_html( $code ) . '</code></td>';
				echo '<td><a href="' . esc_url( $url ) . '">' . esc_html__( 'Un-ignore', 'search-social-appearance-audit' ) . '</a></td>';
				echo '</tr>';
			}
		}
		echo '</tbody></table>';
	}
}

ssaa_render_dashboard_page();
