<?php
/**
 * Health Page.
 *
 * Renders the Internal Link Health report under Helm → Link Health using the
 * Helm design system: headline stat tiles, the orphan-page table (with
 * Fix/Edit/View actions), and the broken-internal-link table. A Rescan button
 * busts the cache and recomputes; Export CSV streams the current report.
 *
 * SECURITY: gated by `manage_options`; rescan and export are nonce-protected.
 *
 * @package Platform\Helm\Modules\Link_Health
 */

declare( strict_types = 1 );

namespace Platform\Helm\Modules\Link_Health;

use Platform\Helm\Core\Ui;

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

final class HealthPage {

	public const PAGE_SLUG   = 'platform-helm-link-health';
	public const PARENT_SLUG = 'platform-helm';

	private const CAPABILITY    = 'manage_options';
	private const RESCAN_ACTION = 'platform_helm_health_rescan';
	private const EXPORT_ACTION = 'platform_helm_health_export';

	public function __construct( private HealthAnalyzer $analyzer ) {}

	public function register_hooks(): void {
		add_action( 'admin_menu', [ $this, 'register_menu' ], 45 );
		add_action( 'admin_init', [ $this, 'maybe_rescan' ] );
		add_action( 'admin_init', [ $this, 'maybe_export_csv' ] );
	}

	public function register_menu(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			return;
		}
		add_submenu_page(
			self::PARENT_SLUG,
			__( 'Link Health', 'platform-helm' ),
			__( 'Link Health', 'platform-helm' ),
			self::CAPABILITY,
			self::PAGE_SLUG,
			[ $this, 'render' ]
		);
	}

	public function maybe_rescan(): void {
		if ( ! isset( $_GET['platform_helm_rescan'] ) ) {
			return;
		}
		if ( ! current_user_can( self::CAPABILITY ) ) {
			return;
		}
		check_admin_referer( self::RESCAN_ACTION );
		$this->analyzer->bust_cache();
		wp_safe_redirect( admin_url( 'admin.php?page=' . self::PAGE_SLUG ) );
		exit;
	}

	/**
	 * Stream the current report (orphans + broken links) as a CSV download.
	 */
	public function maybe_export_csv(): void {
		if ( ! isset( $_GET['platform_helm_health_export'] ) ) {
			return;
		}
		if ( ! current_user_can( self::CAPABILITY ) ) {
			return;
		}
		check_admin_referer( self::EXPORT_ACTION );

		$report = $this->analyzer->get_report();

		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="link-health-' . gmdate( 'Y-m-d' ) . '.csv"' );

		$out = fopen( 'php://output', 'w' );
		fputcsv( $out, [ 'Section', 'Title / Source', 'URL', 'Type / Status' ] );
		foreach ( ( is_array( $report['orphans'] ?? null ) ? $report['orphans'] : [] ) as $o ) {
			fputcsv( $out, [ 'Orphan page', (string) ( $o['title'] ?? '' ), (string) ( $o['view_link'] ?? '' ), (string) ( $o['post_type'] ?? '' ) ] );
		}
		foreach ( ( is_array( $report['broken'] ?? null ) ? $report['broken'] : [] ) as $b ) {
			fputcsv( $out, [ 'Broken link', (string) ( $b['source_title'] ?? '' ), (string) ( $b['url'] ?? '' ), '404' ] );
		}
		fclose( $out );
		exit;
	}

	public function render(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'platform-helm' ) );
		}

		$report = $this->analyzer->get_report();

		$total_posts  = (int) ( $report['total_posts'] ?? 0 );
		$total_links  = (int) ( $report['total_links'] ?? 0 );
		$orphan_count = (int) ( $report['orphan_count'] ?? 0 );
		$broken_count = (int) ( $report['broken_count'] ?? 0 );
		$linked       = max( 0, $total_posts - $orphan_count );
		$age          = (int) ( $report['generated_at'] ?? 0 );

		$rescan_url = wp_nonce_url(
			add_query_arg( 'platform_helm_rescan', '1', admin_url( 'admin.php?page=' . self::PAGE_SLUG ) ),
			self::RESCAN_ACTION
		);
		$export_url = wp_nonce_url(
			add_query_arg( 'platform_helm_health_export', '1', admin_url( 'admin.php?page=' . self::PAGE_SLUG ) ),
			self::EXPORT_ACTION
		);

		$subtitle = $age > 0
			? sprintf(
				/* translators: 1: human time diff, 2: number of pages */
				__( 'Last scan %1$s ago · %2$s pages checked', 'platform-helm' ),
				human_time_diff( $age, time() ),
				number_format_i18n( $total_posts )
			)
			: __( 'A snapshot of how your published content links to itself.', 'platform-helm' );

		$actions  = '<a href="' . esc_url( $export_url ) . '" class="btn btn-ghost"><i class="ti ti-download" aria-hidden="true"></i> ' . esc_html__( 'Export CSV', 'platform-helm' ) . '</a>';
		$actions .= '<a href="' . esc_url( $rescan_url ) . '" class="btn btn-primary"><i class="ti ti-refresh" aria-hidden="true"></i> ' . esc_html__( 'Rescan Now', 'platform-helm' ) . '</a>';

		Ui::open_page( __( 'Link Health', 'platform-helm' ), $subtitle, $actions );

		if ( ! empty( $report['capped'] ) ) {
			Ui::notice(
				sprintf(
					/* translators: %s: scan ceiling */
					esc_html__( 'Large library — the scan was capped at %s posts, so counts are indicative.', 'platform-helm' ),
					number_format_i18n( (int) ( $report['scan_ceiling'] ?? 0 ) )
				),
				'info'
			);
		}

		// Headline stats — all derived from real scan data.
		echo '<div class="stat-grid stat-grid-5">';
		Ui::stat_tile( __( 'Pages Checked', 'platform-helm' ), number_format_i18n( $total_posts ), 'neutral', 'ti-file-search', __( 'Full site scan', 'platform-helm' ), '' );
		Ui::stat_tile(
			__( 'Linked Pages', 'platform-helm' ),
			number_format_i18n( $linked ),
			'green',
			'ti-circle-check',
			$total_posts > 0 ? sprintf( /* translators: %d: percent */ __( '%d%% have inbound links', 'platform-helm' ), (int) round( $linked / $total_posts * 100 ) ) : '',
			'up'
		);
		Ui::stat_tile( __( 'Orphan Pages', 'platform-helm' ), number_format_i18n( $orphan_count ), 'amber', 'ti-file-x', __( 'No inbound links', 'platform-helm' ), $orphan_count > 0 ? 'warn' : '', 'amber' );
		Ui::stat_tile( __( 'Broken Links', 'platform-helm' ), number_format_i18n( $broken_count ), 'red', 'ti-unlink', __( 'Needs attention', 'platform-helm' ), $broken_count > 0 ? 'danger' : '', $broken_count > 0 ? 'red' : '' );
		Ui::stat_tile( __( 'Internal Links', 'platform-helm' ), number_format_i18n( $total_links ), 'blue', 'ti-link', __( 'Across your content', 'platform-helm' ), '' );
		echo '</div>';

		$this->render_orphans_card( is_array( $report['orphans'] ?? null ) ? $report['orphans'] : [], $orphan_count );
		$this->render_broken_card( is_array( $report['broken'] ?? null ) ? $report['broken'] : [], $broken_count );

		Ui::close_page();
	}

	/**
	 * Resolve the Link Architect admin URL, but only when that module is
	 * enabled. Empty string = skip the "Fix" affordances rather than 404.
	 */
	private function architect_url(): string {
		$opts    = get_option( 'platform_helm_settings', [] );
		$enabled = is_array( $opts ) && ! empty( $opts['module_link_architect'] );
		return $enabled ? admin_url( 'admin.php?page=platform-helm-link-architect' ) : '';
	}

	/**
	 * @param array<int,array<string,mixed>> $orphans
	 */
	private function render_orphans_card( array $orphans, int $count ): void {
		$architect_base = $this->architect_url();

		echo '<div class="card mb-16">';
		echo '<div class="card-header">';
		echo '<div class="card-title"><i class="ti ti-file-x" style="color:var(--warning)" aria-hidden="true"></i> ' . esc_html__( 'Orphan Pages', 'platform-helm' );
		if ( $count > 0 ) {
			echo ' <span class="badge badge-warning">' . esc_html( number_format_i18n( $count ) ) . '</span>';
		}
		echo '</div>';
		echo '<div style="display:flex;gap:10px;align-items:center">';
		echo '<span class="text-faint">' . esc_html__( 'Pages with no inbound internal links', 'platform-helm' ) . '</span>';
		if ( '' !== $architect_base && ! empty( $orphans ) ) {
			$bulk = [];
			foreach ( $orphans as $o ) {
				if ( ! empty( $o['view_link'] ) ) {
					$bulk[] = (string) $o['view_link'];
				}
				if ( count( $bulk ) >= 25 ) {
					break;
				}
			}
			if ( ! empty( $bulk ) ) {
				$bulk_url = add_query_arg( [ 'prefill_url' => array_map( 'rawurlencode', $bulk ) ], $architect_base );
				echo '<a class="btn btn-ghost btn-sm" href="' . esc_url( $bulk_url ) . '">' . esc_html(
					sprintf( /* translators: %d: count */ _n( 'Bulk Fix (%d)', 'Bulk Fix (%d)', count( $bulk ), 'platform-helm' ), count( $bulk ) )
				) . '</a>';
			}
		}
		echo '</div></div>';

		if ( empty( $orphans ) ) {
			echo '<div class="card-body"><p class="text-secondary">' . esc_html__( 'No orphan pages — every published post has at least one internal link pointing to it.', 'platform-helm' ) . '</p></div></div>';
			return;
		}

		echo '<div class="table-wrap"><table><thead><tr>';
		echo '<th>' . esc_html__( 'Page', 'platform-helm' ) . '</th>';
		echo '<th>' . esc_html__( 'Type', 'platform-helm' ) . '</th>';
		echo '<th>' . esc_html__( 'Last Modified', 'platform-helm' ) . '</th>';
		echo '<th class="right">' . esc_html__( 'Actions', 'platform-helm' ) . '</th>';
		echo '</tr></thead><tbody>';

		foreach ( $orphans as $o ) {
			$id       = (int) ( $o['id'] ?? 0 );
			$path     = ! empty( $o['view_link'] ) ? wp_make_link_relative( (string) $o['view_link'] ) : '';
			$mod_ts   = $id ? (int) get_post_modified_time( 'U', false, $id ) : 0;
			$mod_text = $mod_ts ? sprintf( /* translators: %s: time diff */ __( '%s ago', 'platform-helm' ), human_time_diff( $mod_ts, time() ) ) : '—';
			$pt_badge = ( 'page' === ( $o['post_type'] ?? '' ) ) ? 'badge-info' : 'badge-neutral';
			$fix_url  = ( '' !== $architect_base && ! empty( $o['view_link'] ) )
				? add_query_arg( [ 'prefill_url' => rawurlencode( (string) $o['view_link'] ) ], $architect_base )
				: '';

			echo '<tr>';
			echo '<td><p class="url-cell">' . esc_html( '' !== $path ? $path : (string) $o['title'] ) . '</p><p class="meta-line">' . esc_html( (string) $o['title'] ) . '</p></td>';
			echo '<td><span class="badge ' . esc_attr( $pt_badge ) . '">' . esc_html( (string) $o['post_type'] ) . '</span></td>';
			echo '<td><span style="color:var(--text-muted)">' . esc_html( $mod_text ) . '</span></td>';
			echo '<td class="right">';
			if ( '' !== $fix_url ) {
				echo '<a class="btn btn-primary btn-sm" href="' . esc_url( $fix_url ) . '">' . esc_html__( 'Fix Links', 'platform-helm' ) . '</a> ';
			}
			if ( ! empty( $o['edit_link'] ) ) {
				echo '<a class="btn btn-ghost btn-sm" href="' . esc_url( (string) $o['edit_link'] ) . '">' . esc_html__( 'Edit', 'platform-helm' ) . '</a> ';
			}
			if ( ! empty( $o['view_link'] ) ) {
				echo '<a class="btn btn-ghost btn-sm" href="' . esc_url( (string) $o['view_link'] ) . '" target="_blank" rel="noopener">' . esc_html__( 'View', 'platform-helm' ) . '</a>';
			}
			echo '</td></tr>';
		}
		echo '</tbody></table></div></div>';
	}

	/**
	 * @param array<int,array<string,mixed>> $broken
	 */
	private function render_broken_card( array $broken, int $count ): void {
		echo '<div class="card">';
		echo '<div class="card-header">';
		echo '<div class="card-title"><i class="ti ti-unlink" style="color:var(--danger)" aria-hidden="true"></i> ' . esc_html__( 'Broken Links', 'platform-helm' );
		if ( $count > 0 ) {
			echo ' <span class="badge badge-danger">' . esc_html( number_format_i18n( $count ) ) . '</span>';
		}
		echo '</div>';
		echo '<span class="text-faint">' . esc_html__( 'Internal links pointing to missing or trashed content', 'platform-helm' ) . '</span>';
		echo '</div>';

		if ( empty( $broken ) ) {
			echo '<div class="card-body"><p class="text-secondary">' . esc_html__( 'No broken internal links found.', 'platform-helm' ) . '</p></div></div>';
			return;
		}

		echo '<div class="table-wrap"><table><thead><tr>';
		echo '<th>' . esc_html__( 'Source Page', 'platform-helm' ) . '</th>';
		echo '<th>' . esc_html__( 'Broken URL', 'platform-helm' ) . '</th>';
		echo '<th>' . esc_html__( 'Status', 'platform-helm' ) . '</th>';
		echo '<th class="right">' . esc_html__( 'Actions', 'platform-helm' ) . '</th>';
		echo '</tr></thead><tbody>';

		foreach ( $broken as $b ) {
			$edit = get_edit_post_link( (int) ( $b['source_id'] ?? 0 ) );
			echo '<tr>';
			echo '<td><p class="url-cell">' . esc_html( (string) ( $b['source_title'] ?? '' ) ) . '</p></td>';
			echo '<td><p style="font-family:var(--font-mono);font-size:11px;color:var(--danger);word-break:break-all;margin:0">' . esc_html( (string) ( $b['url'] ?? '' ) ) . '</p></td>';
			echo '<td><span class="badge badge-danger">404</span></td>';
			echo '<td class="right">';
			if ( $edit ) {
				echo '<a class="btn btn-primary btn-sm" href="' . esc_url( (string) $edit ) . '">' . esc_html__( 'Update Link', 'platform-helm' ) . '</a>';
			}
			echo '</td></tr>';
		}
		echo '</tbody></table></div></div>';
	}
}
