<?php
/**
 * Export Tool admin page
 *
 * Offers a simple form that lets site administrators download the full
 * SlideMind dataset as a single JSON file (data portability). Complements
 * the existing Settings > Data tab bulk export by being visible in free
 * builds and by exposing learner memory variables.
 *
 * The heavy lifting is delegated to `SlideMind\Core\FullExporter`; this
 * class owns the menu registration, form handling, nonce, and download
 * headers.
 *
 * @package SlideMind\Admin
 * @since   0.5.0
 */

namespace SlideMind\Admin;

use SlideMind\Core\FullExporter;

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

class ExportToolPage {

	const PAGE_SLUG   = 'slidemind-export-tool';
	const NONCE_NAME  = 'slidemind_full_export_nonce';
	const NONCE_ACTION = 'slidemind_full_export';
	const ACTION      = 'slidemind_full_export';
	const CAPABILITY  = 'manage_slidemind_settings';

	/**
	 * @var FullExporter
	 */
	private $full_exporter;

	public function __construct( FullExporter $full_exporter ) {
		$this->full_exporter = $full_exporter;

		add_action( 'admin_post_' . self::ACTION, [ $this, 'handle_export' ] );
	}

	/**
	 * Registers the admin submenu under the SlideMind main menu.
	 *
	 * Called from `AdminMenu::register_menu()`.
	 *
	 * @param string $parent_slug Parent menu slug.
	 * @param string $capability  Capability required to see the page.
	 */
	public function register_submenu( string $parent_slug, string $capability ): void {
		add_submenu_page(
			$parent_slug,
			__( 'Export & Import', 'slidemind' ),
			__( 'Export & Import', 'slidemind' ),
			$capability,
			self::PAGE_SLUG,
			[ $this, 'render' ]
		);
	}

	/**
	 * Renders the export form view.
	 */
	public function render(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'Unauthorized access', 'slidemind' ) );
		}

		// phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- Controlled array of view vars.
		extract( $this->get_view_data(), EXTR_SKIP );

		include SLIDEMIND_PLUGIN_PATH . 'admin/views/export-import.php';
	}

	/**
	 * Returns the data needed by the export form view.
	 *
	 * Shared between the standalone Export page and the Settings →
	 * Export/Import Data tab so both surfaces offer the same section list and
	 * counts without duplicating the business logic.
	 *
	 * @return array<string, mixed>
	 */
	public function get_view_data(): array {
		if ( ! current_user_can( 'manage_slidemind_settings' ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'slidemind' ) );
		}

		$sections = [
			'courses'            => __( 'Courses', 'slidemind' ),
			'modules'            => __( 'Modules', 'slidemind' ),
			'slides'             => __( 'Slides', 'slidemind' ),
			'templates'          => __( 'Custom templates', 'slidemind' ),
			'memory_variables'   => __( 'Learner memory (variables saved by learners)', 'slidemind' ),
			'memory_definitions' => __( 'Memory definitions (metadata)', 'slidemind' ),
			'settings'           => __( 'Plugin settings (without API keys)', 'slidemind' ),
		];

		$counts_items = $this->counts_and_items();

		return [
			'sections'       => $sections,
			'counts'         => $counts_items['counts'],
			'items'          => $counts_items['items'],
			'action_url'     => admin_url( 'admin-post.php' ),
			'nonce_name'     => self::NONCE_NAME,
			'nonce_action'   => self::NONCE_ACTION,
			'action_slug'    => self::ACTION,
			'upgrade_url'    => \SlideMind\Core\FeatureGate::get_upgrade_url(),
			'status'         => isset( $_GET['exported'] ) ? sanitize_key( (string) wp_unslash( $_GET['exported'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only flag after a POST redirect; capability checked above; value sanitized with sanitize_key().
			'admin_ajax_url' => admin_url( 'admin-ajax.php' ),
			'admin_nonce'    => wp_create_nonce( 'slidemind_admin_nonce' ),
		];
	}

	/**
	 * Handles the admin-post.php submission and streams the JSON download.
	 */
	public function handle_export(): void {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'Unauthorized access', 'slidemind' ), '', [ 'response' => 403 ] );
		}

		check_admin_referer( self::NONCE_ACTION, self::NONCE_NAME );

		$requested = isset( $_POST['sections'] ) && is_array( $_POST['sections'] )
			? array_map( 'sanitize_key', wp_unslash( $_POST['sections'] ) )
			: [];

		if ( empty( $requested ) ) {
			$redirect = add_query_arg( 'exported', 'empty', admin_url( 'admin.php?page=slidemind-settings' ) ) . '#data';
			wp_safe_redirect( $redirect );
			exit;
		}

		// Item-level allowlist per section, sanitized to positive ints.
		$item_ids_by_section = [];
		if ( isset( $_POST['item_ids'] ) && is_array( $_POST['item_ids'] ) ) {
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- nested array sanitized below via array_map intval.
			$raw = wp_unslash( $_POST['item_ids'] );
			foreach ( [ 'courses', 'modules', 'slides', 'templates' ] as $section ) {
				if ( isset( $raw[ $section ] ) && is_array( $raw[ $section ] ) ) {
					$ids = array_values( array_filter( array_map( 'intval', $raw[ $section ] ), static fn( $i ) => $i > 0 ) );
					if ( ! empty( $ids ) ) {
						$item_ids_by_section[ $section ] = $ids;
					}
				}
			}
		}

		$json = $this->full_exporter->export_json( $requested, $item_ids_by_section );

		nocache_headers();
		header( 'Content-Type: application/json; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $this->full_exporter->suggested_filename() . '"' );
		header( 'Content-Length: ' . strlen( $json ) );

		echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON payload sent as a file download.
		exit;
	}

	/**
	 * Counts + per-section item lists (id+title) for the UI tree.
	 *
	 * @return array{counts:array<string,int>,items:array<string,array<int,array{id:int,title:string}>>}
	 */
	private function counts_and_items(): array {
		$plugin    = \SlideMind\Plugin::instance();
		$repo      = $plugin->get_config_repository();
		$templates = $plugin->get_template_manager();

		$courses_items = [];
		foreach ( $repo->get_courses( 'any' ) as $c ) {
			$courses_items[] = [ 'id' => (int) $c['id'], 'title' => (string) $c['title'] ];
		}
		$modules_items = [];
		foreach ( $repo->get_all_modules( 'any' ) as $m ) {
			$modules_items[] = [
				'id'                  => (int) $m['id'],
				'title'               => (string) $m['title'],
				'parent_course_id'    => (int) ( $m['parent_course_id'] ?? 0 ),
				'parent_course_title' => (string) ( $m['parent_course_title'] ?? '' ),
			];
		}
		$slides_items = [];
		foreach ( $repo->get_all_slides( 'any' ) as $s ) {
			$slides_items[] = [
				'id'                  => (int) $s['id'],
				'title'               => (string) $s['title'],
				'parent_module_id'    => (int) ( $s['parent_module_id'] ?? 0 ),
				'parent_module_title' => (string) ( $s['parent_module_title'] ?? '' ),
			];
		}

		$templates_items = [];
		$custom_count    = 0;
		foreach ( $templates->get_all() as $tpl ) {
			if ( ! empty( $tpl['is_default'] ) ) {
				continue;
			}
			$custom_count++;
			$slug              = (string) ( $tpl['slug'] ?? '' );
			$templates_items[] = [
				'id'    => $slug !== '' ? crc32( $slug ) : 0,
				'title' => (string) ( $tpl['title'] ?? '' ),
				'slug'  => $slug,
			];
		}

		global $wpdb;
		$table = $wpdb->prefix . 'slidemind_learner_memory';
		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin-owned table count.
		$memory_rows = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table ) );
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

		$defs = get_option( 'slidemind_memory_definitions', [] );

		return [
			'counts' => [
				'courses'            => count( $courses_items ),
				'modules'            => count( $modules_items ),
				'slides'             => count( $slides_items ),
				'templates'          => $custom_count,
				'memory_variables'   => $memory_rows,
				'memory_definitions' => is_array( $defs ) ? count( $defs ) : 0,
				'settings'           => 1,
			],
			'items'  => [
				'courses'   => $courses_items,
				'modules'   => $modules_items,
				'slides'    => $slides_items,
				'templates' => $templates_items,
			],
		];
	}
}
