<?php
/**
 * Activity Maintenance.
 *
 * Operational extras for the Activity Log:
 *   - CSV export (admin-post handler, streamed download, capability + nonce).
 *   - Retention: a daily cron prunes entries older than the configured number
 *     of days (0 = keep forever). Cron is cleared on deactivation.
 *   - A small recent-activity feed for the Command Center dashboard.
 *
 * @package Platform\Helm\Modules\Activity_Log
 */

declare( strict_types = 1 );

namespace Platform\Helm\Modules\Activity_Log;

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

final class ActivityMaintenance {

	public const CRON_HOOK     = 'platform_helm_activity_prune';
	public const RETENTION_KEY = 'activity_retention_days'; // in main settings option.
	private const EXPORT_ACTION = 'platform_helm_export_activity';
	private const CAPABILITY     = 'manage_options';

	public function __construct( private ActivityLogger $logger ) {}

	public function register_hooks(): void {
		add_action( 'admin_post_' . self::EXPORT_ACTION, [ $this, 'handle_export' ] );
		add_action( self::CRON_HOOK, [ $this, 'run_prune' ] );
		add_action( 'admin_init', [ $this, 'maybe_schedule' ] );
		add_filter( 'platform_helm_dashboard_metrics', [ $this, 'supply_feed' ] );
	}

	/* ---------- retention cron ---------- */

	public function maybe_schedule(): void {
		if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
			wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', self::CRON_HOOK );
		}
	}

	public static function unschedule(): void {
		$ts = wp_next_scheduled( self::CRON_HOOK );
		if ( false !== $ts ) {
			wp_unschedule_event( $ts, self::CRON_HOOK );
		}
		wp_clear_scheduled_hook( self::CRON_HOOK );
	}

	public function run_prune(): void {
		$days = $this->retention_days();
		if ( $days > 0 ) {
			$this->logger->prune_older_than( $days );
		}
	}

	private function retention_days(): int {
		$opts = get_option( 'platform_helm_settings', [] );
		$days = is_array( $opts ) ? (int) ( $opts[ self::RETENTION_KEY ] ?? 0 ) : 0;
		return max( 0, min( 3650, $days ) ); // cap at ~10 years.
	}

	/* ---------- CSV export ---------- */

	public static function export_url( string $action_filter = '' ): string {
		$url = add_query_arg(
			[ 'action' => self::EXPORT_ACTION, 'action_filter' => $action_filter ],
			admin_url( 'admin-post.php' )
		);
		return wp_nonce_url( $url, self::EXPORT_ACTION );
	}

	public function handle_export(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'Permission denied.', 'platform-helm' ) );
		}
		check_admin_referer( self::EXPORT_ACTION );

		$filter = isset( $_GET['action_filter'] ) ? sanitize_key( wp_unslash( (string) $_GET['action_filter'] ) ) : '';
		$rows   = $this->logger->all_for_export( $filter );

		$filename = 'platform-helm-activity-' . gmdate( 'Y-m-d-His' ) . '.csv';

		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename=' . $filename );

		$out = fopen( 'php://output', 'w' );
		// Header row.
		fputcsv( $out, [ 'Date (UTC)', 'User', 'Action', 'Object type', 'Object ID', 'Description' ] );
		foreach ( $rows as $r ) {
			fputcsv( $out, [
				(string) ( $r['logged_at'] ?? '' ),
				(string) ( $r['user_name'] ?? '' ),
				(string) ( $r['action'] ?? '' ),
				(string) ( $r['object_type'] ?? '' ),
				(string) ( $r['object_id'] ?? '' ),
				(string) ( $r['description'] ?? '' ),
			] );
		}
		fclose( $out ); // phpcs:ignore
		exit;
	}

	/* ---------- dashboard feed ---------- */

	/**
	 * Supply the most recent few events to the Command Center via the shared
	 * dashboard-metrics filter.
	 *
	 * @param array<string,mixed> $metrics
	 * @return array<string,mixed>
	 */
	public function supply_feed( array $metrics ): array {
		$rows = $this->logger->recent( 6, 0, '' );
		$feed = [];
		foreach ( $rows as $r ) {
			$ts = strtotime( (string) ( $r['logged_at'] ?? '' ) );
			$feed[] = [
				'when'        => $ts ? human_time_diff( $ts, time() ) : '',
				'description' => (string) ( $r['description'] ?? '' ),
				'action'      => (string) ( $r['action'] ?? '' ),
			];
		}
		$metrics['activity_feed'] = $feed;
		return $metrics;
	}
}
