<?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' ) );
        }
        // Courses, modules and custom templates are paid-plan features and
        // are absent from the free build. The hierarchy sections are added
        // only in the premium build.
        $sections = [];
        $sections['slides'] = __( 'Slides', 'slidemind' );
        $sections['memory_variables'] = __( 'Learner memory (variables saved by learners)', 'slidemind' );
        $sections['memory_definitions'] = __( 'Memory definitions (metadata)', 'slidemind' );
        $sections['settings'] = __( 'Plugin settings (without API keys)', 'slidemind' );
        $counts_items = $this->counts_and_items();
        $upgrade_url = '';
        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'    => $upgrade_url,
            'status'         => ( isset( $_GET['exported'] ) ? sanitize_key( (string) wp_unslash( $_GET['exported'] ) ) : '' ),
            '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 = [];
        $modules_items = [];
        $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;
        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,
            ],
        ];
    }

}
