<?php
/**
 * File Path: includes/admin/class-mbs-activity-log-admin.php
 *
 * Activity Log Admin Page (INSIGHTS-2)
 *
 * Tools > Activity Log sub-menu page. PUB-gated. Provides:
 *   - Paginated table (50 rows/page) with user, action, book, meta, date columns.
 *   - Filter bar: user, action, date range.
 *   - CSV export that respects active filters.
 *
 * @package MyBookShowroom
 * @since   4.4.0
 */

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

/**
 * Class MBS_Activity_Log_Admin
 *
 * @since 4.4.0
 */
class MBS_Activity_Log_Admin {

	/**
	 * Register the admin sub-menu page and CSV export handler.
	 *
	 * @return void
	 * @since 4.4.0
	 */
	public static function register_hooks(): void {
		add_action( 'save_post_' . MBS_POST_TYPE, array( __CLASS__, 'on_book_save' ), 20, 2 );
		add_action( 'mbs_export_complete',   array( __CLASS__, 'on_export' ),   10, 2 );
		add_action( 'mbs_import_complete',   array( __CLASS__, 'on_import' ),   10, 3 );
		add_action( 'mbs_arc_send_complete', array( __CLASS__, 'on_arc_send' ), 10, 2 );
	}

	public static function register(): void {
		add_action( 'admin_menu', array( __CLASS__, 'add_submenu' ) );
	}

	/**
	 * Add "Activity Log" under the Tools menu.
	 *
	 * @return void
	 * @since 4.4.0
	 */
	public static function add_submenu(): void {
		// Removed from sidebar -- accessible via dashboard quick-action tile.
		add_submenu_page(
			null,
			__( 'Activity Log', 'my-book-showroom' ),
			__( 'Activity Log', 'my-book-showroom' ),
			'manage_options',
			'mbs-activity-log',
			array( __CLASS__, 'render' )
		);
	}

	/**
	 * Render the Activity Log admin page.
	 *
	 * @return void
	 * @since 4.4.0
	 */
	public static function render(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to view this page.', 'my-book-showroom' ) );
		}

		// PUB gate.
		if ( ! mbs_is_pub() ) {
			?>
			<div class="wrap">
				<h1><?php esc_html_e( 'Activity Log', 'my-book-showroom' ); ?></h1>
				<!-- MBS: Activity Log requires PUB license -->
				<div class="notice notice-info">
					<p>
						<?php
						printf(
							/* translators: %s: upgrade link */
							esc_html__( 'The Activity Log requires a Publisher (PUB) license. %s', 'my-book-showroom' ),
							'<a href="' . esc_url( MBS_UPGRADE_URL ) . '" target="_blank" rel="noopener noreferrer">' .
							esc_html__( 'Upgrade to PUB', 'my-book-showroom' ) . ' &rarr;</a>'
						);
						?>
					</p>
				</div>
			</div>
			<?php
			return;
		}

		// Handle CSV export request.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$is_export = isset( $_GET['mbs_export_log'] ) && '1' === $_GET['mbs_export_log'];
		if ( $is_export ) {
			check_admin_referer( 'mbs_export_activity_log' );
			self::stream_csv_export();
			return;
		}

		// Build filter args from GET params.
		$filter_user    = absint( $_GET['filter_user'] ?? 0 );
		$filter_action  = sanitize_key( wp_unslash( $_GET['filter_action'] ?? '' ) );
		$filter_from    = sanitize_text_field( wp_unslash( $_GET['filter_from'] ?? '' ) );
		$filter_to      = sanitize_text_field( wp_unslash( $_GET['filter_to'] ?? '' ) );
		$current_page   = max( 1, absint( $_GET['paged'] ?? 1 ) );
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		$filter_args = array(
			'user_id'   => $filter_user ?: null,
			'action'    => $filter_action ?: null,
			'date_from' => $filter_from ?: null,
			'date_to'   => $filter_to ?: null,
			'per_page'  => 50,
			'page'      => $current_page,
		);

		$result     = MBS_Activity_Log_DAO::get_filtered( $filter_args );
		$rows       = $result['rows'];
		$total      = $result['total'];
		$total_pages = max( 1, (int) ceil( $total / 50 ) );

		// All WP users who appear in the log (for filter dropdown).
		$log_users = MBS_Activity_Log_DAO::get_distinct_user_ids();

		$action_labels = self::get_action_labels();

		// Export URL (keeps active filters).
		$export_args = array_merge(
			array_filter( array(
				'filter_user'   => $filter_user ?: '',
				'filter_action' => $filter_action,
				'filter_from'   => $filter_from,
				'filter_to'     => $filter_to,
			) ),
			array(
				'page'           => 'mbs-activity-log',
				'mbs_export_log' => '1',
				'_wpnonce'       => wp_create_nonce( 'mbs_export_activity_log' ),
			)
		);
		$export_url  = add_query_arg( $export_args, admin_url( 'admin.php' ) );
		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Activity Log', 'my-book-showroom' ); ?></h1>

			<!-- Filter bar -->
			<form method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>" class="mbs-log-filter-form" style="margin-bottom:16px;display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;">
				<input type="hidden" name="page" value="mbs-activity-log" />

				<div>
					<label for="mbs-filter-user" style="display:block;font-weight:600;margin-bottom:4px;"><?php esc_html_e( 'User', 'my-book-showroom' ); ?></label>
					<select id="mbs-filter-user" name="filter_user">
						<option value=""><?php esc_html_e( 'All Users', 'my-book-showroom' ); ?></option>
						<?php foreach ( $log_users as $uid ) : ?>
							<?php $ud = get_userdata( (int) $uid ); ?>
							<option value="<?php echo esc_attr( $uid ); ?>" <?php selected( $filter_user, $uid ); ?>>
								<?php echo esc_html( $ud ? $ud->display_name : '#' . $uid ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</div>

				<div>
					<label for="mbs-filter-action" style="display:block;font-weight:600;margin-bottom:4px;"><?php esc_html_e( 'Action', 'my-book-showroom' ); ?></label>
					<select id="mbs-filter-action" name="filter_action">
						<option value=""><?php esc_html_e( 'All Actions', 'my-book-showroom' ); ?></option>
						<?php foreach ( $action_labels as $slug => $label ) : ?>
							<option value="<?php echo esc_attr( $slug ); ?>" <?php selected( $filter_action, $slug ); ?>>
								<?php echo esc_html( $label ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</div>

				<div>
					<label for="mbs-filter-from" style="display:block;font-weight:600;margin-bottom:4px;"><?php esc_html_e( 'From Date', 'my-book-showroom' ); ?></label>
					<input type="date" id="mbs-filter-from" name="filter_from" value="<?php echo esc_attr( $filter_from ); ?>" />
				</div>

				<div>
					<label for="mbs-filter-to" style="display:block;font-weight:600;margin-bottom:4px;"><?php esc_html_e( 'To Date', 'my-book-showroom' ); ?></label>
					<input type="date" id="mbs-filter-to" name="filter_to" value="<?php echo esc_attr( $filter_to ); ?>" />
				</div>

				<div style="display:flex;gap:8px;">
					<button type="submit" class="button"><?php esc_html_e( 'Filter', 'my-book-showroom' ); ?></button>
					<a href="<?php echo esc_url( admin_url( 'admin.php?page=mbs-activity-log' ) ); ?>" class="button"><?php esc_html_e( 'Reset', 'my-book-showroom' ); ?></a>
				</div>
			</form>

			<div style="margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;">
				<span style="color:#50575e;">
					<?php
					printf(
						/* translators: %d: total count */
						esc_html__( '%d entries found', 'my-book-showroom' ),
						$total // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- integer value, safe with %d format
					);
					?>
				</span>
				<a href="<?php echo esc_url( $export_url ); ?>" class="button">
					<?php esc_html_e( 'Export CSV', 'my-book-showroom' ); ?>
				</a>
			</div>

			<table class="widefat striped mbs-activity-log-table">
				<thead>
					<tr>
						<th style="width:50px;"><?php esc_html_e( 'ID', 'my-book-showroom' ); ?></th>
						<th><?php esc_html_e( 'Book', 'my-book-showroom' ); ?></th>
						<th><?php esc_html_e( 'User', 'my-book-showroom' ); ?></th>
						<th style="width:100px;"><?php esc_html_e( 'Action', 'my-book-showroom' ); ?></th>
						<th><?php esc_html_e( 'Details', 'my-book-showroom' ); ?></th>
						<th style="width:160px;"><?php esc_html_e( 'Date', 'my-book-showroom' ); ?></th>
					</tr>
				</thead>
				<tbody>
				<?php if ( empty( $rows ) ) : ?>
					<tr>
						<td colspan="6" style="text-align:center;padding:20px;">
							<?php esc_html_e( 'No entries match the current filters.', 'my-book-showroom' ); ?>
						</td>
					</tr>
				<?php else : ?>
					<?php foreach ( $rows as $entry ) : ?>
						<?php
						$book_id    = (int) $entry->book_id;
						$book_title = $book_id > 0 ? get_the_title( $book_id ) : __( 'System', 'my-book-showroom' );
						$book_link  = $book_id > 0 ? get_edit_post_link( $book_id ) : '';
						$user_data  = get_userdata( (int) $entry->user_id );
						$user_label = $user_data ? $user_data->display_name : __( 'Unknown', 'my-book-showroom' );
						$action_lbl = $action_labels[ $entry->action ] ?? esc_html( $entry->action );
						$meta_str   = '';
						if ( ! empty( $entry->meta ) ) {
							$meta_arr = json_decode( $entry->meta, true );
							if ( is_array( $meta_arr ) ) {
								$parts = array();
								foreach ( $meta_arr as $mk => $mv ) {
									$parts[] = '<strong>' . esc_html( $mk ) . ':</strong> ' . esc_html( $mv );
								}
								$meta_str = implode( ', ', $parts );
							}
						}
						?>
						<tr>
							<td><?php echo (int) $entry->id; ?></td>
							<td>
								<?php if ( $book_link ) : ?>
									<a href="<?php echo esc_url( $book_link ); ?>"><?php echo esc_html( $book_title ); ?></a>
								<?php else : ?>
									<?php echo esc_html( $book_title ); ?>
								<?php endif; ?>
							</td>
							<td><?php echo esc_html( $user_label ); ?></td>
							<td><span class="mbs-log-action mbs-log-action-<?php echo esc_attr( $entry->action ); ?>"><?php echo esc_html( $action_lbl ); ?></span></td>
							<td><?php echo wp_kses( $meta_str, array( 'strong' => array() ) ); ?></td>
							<td><?php echo esc_html( $entry->created_at ); ?></td>
						</tr>
					<?php endforeach; ?>
				<?php endif; ?>
				</tbody>
			</table>

			<!-- Pagination -->
			<?php if ( $total_pages > 1 ) : ?>
			<div class="tablenav bottom" style="margin-top:12px;">
				<?php
				$base_url = add_query_arg( array_filter( array(
					'page'          => 'mbs-activity-log',
					'filter_user'   => $filter_user ?: '',
					'filter_action' => $filter_action,
					'filter_from'   => $filter_from,
					'filter_to'     => $filter_to,
				) ), admin_url( 'admin.php' ) );
				echo paginate_links( array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted renderer returns pre-escaped HTML
					'base'      => $base_url . '%_%',
					'format'    => '&paged=%#%',
					'current'   => $current_page,
					'total'     => $total_pages,
					'prev_text' => '&laquo;',
					'next_text' => '&raquo;',
				) );
				?>
			</div>
			<?php endif; ?>
		</div><!-- .wrap -->
		<?php
	}

	/**
	 * Stream filtered log entries as a CSV file download.
	 *
	 * Reads active GET filters, calls MBS_Activity_Log_DAO::export_csv(),
	 * streams with Content-Disposition: attachment.
	 *
	 * @return void Does not return.
	 * @since 4.4.0
	 */
	private static function stream_csv_export(): void {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$args = array(
			'user_id'   => absint( $_GET['filter_user'] ?? 0 ) ?: null,
			'action'    => sanitize_key( wp_unslash( $_GET['filter_action'] ?? '' ) ) ?: null,
			'date_from' => sanitize_text_field( wp_unslash( $_GET['filter_from'] ?? '' ) ) ?: null,
			'date_to'   => sanitize_text_field( wp_unslash( $_GET['filter_to'] ?? '' ) ) ?: null,
		);
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		$rows     = MBS_Activity_Log_DAO::export_csv( $args );
		$filename = 'mbs-activity-log-' . gmdate( 'Y-m-d' ) . '.csv';

		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
		header( 'Cache-Control: no-store, no-cache' );

		$output = fopen( 'php://output', 'w' );
		if ( ! empty( $rows ) ) {
			fputcsv( $output, array_keys( $rows[0] ) );
			foreach ( $rows as $row ) {
				fputcsv( $output, array_values( $row ) );
			}
		} else {
			fputcsv( $output, array( 'ID', 'Book', 'User', 'Action', 'Meta', 'Date' ) );
		}
		fclose( $output ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- WP_Filesystem migration deferred to PC-FILESYS sprint; PHP native file ops are safe here (temp files in get_temp_dir(), never inside wp-content)
		exit;
	}

	/**
	 * Return human-readable labels for all known action types.
	 *
	 * @return array<string, string>
	 * @since 4.4.0
	 */
	public static function get_action_labels(): array {
		return array(
			'publish'  => __( 'Published', 'my-book-showroom' ),
			'draft'    => __( 'Saved as Draft', 'my-book-showroom' ),
			'edit'     => __( 'Edited', 'my-book-showroom' ),
			'import'   => __( 'Import', 'my-book-showroom' ),
			'export'   => __( 'Export', 'my-book-showroom' ),
			'arc_send' => __( 'ARC Sent', 'my-book-showroom' ),
		);
	}
	// ── RF-008: Named hook callbacks (extracted from MBS_Plugin::load_data_layer()) ──

	/**
	 * Log a book save event to the activity log.
	 *
	 * Hooked to save_post_mbs_book at priority 20. Guards against autosave
	 * and capability checks before logging.
	 *
	 * @param int     $post_id Post ID.
	 * @param WP_Post $post    Post object.
	 * @return void
	 */
	public static function on_book_save( int $post_id, WP_Post $post ): void {
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; }
		if ( ! current_user_can( 'edit_post', $post_id ) ) { return; }
		$action = ( 'publish' === $post->post_status ) ? 'publish' :
		          ( 'draft' === $post->post_status ? 'draft' : 'edit' );
		MBS_Activity_Log_DAO::log_edit( $post_id, get_current_user_id(), $action );
	}

	/**
	 * Log a CSV/XLSX export event.
	 *
	 * Hooked to mbs_export_complete. book_id = 0 indicates a system-level event.
	 *
	 * @param string $format    Export format identifier (e.g. 'csv', 'xlsx').
	 * @param int    $row_count Number of rows exported.
	 * @return void
	 */
	public static function on_export( string $format, int $row_count ): void {
		MBS_Activity_Log_DAO::log_edit( 0, get_current_user_id(), 'export', array( 'format' => $format, 'row_count' => $row_count ) );
	}

	/**
	 * Log a CSV import completion event.
	 *
	 * Hooked to mbs_import_complete.
	 *
	 * @param string $filename      Original filename.
	 * @param int    $row_count     Number of rows imported.
	 * @param string $importer_type Importer class identifier.
	 * @return void
	 */
	public static function on_import( string $filename, int $row_count, string $importer_type ): void {
		MBS_Activity_Log_DAO::log_edit( 0, get_current_user_id(), 'import', array( 'filename' => $filename, 'row_count' => $row_count, 'importer' => $importer_type ) );
	}

	/**
	 * Log an ARC email send event.
	 *
	 * Hooked to mbs_arc_send_complete.
	 *
	 * @param int $book_id        Post ID of the book.
	 * @param int $reviewer_count Number of ARC reviewers emailed.
	 * @return void
	 */
	public static function on_arc_send( int $book_id, int $reviewer_count ): void {
		MBS_Activity_Log_DAO::log_edit( $book_id, get_current_user_id(), 'arc_send', array( 'reviewer_count' => $reviewer_count ) );
	}

}
