<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * Admin controller - metabox registration, save handler, asset enqueue.
 */
class TNC_Flipbook_3D_Admin {

    public static function init() {
        add_action( 'add_meta_boxes',            array( __CLASS__, 'register_metaboxes' ) );
        add_filter( 'get_user_option_meta-box-order_' . TNC_FLIPBOOK_3D_CPT, array( __CLASS__, 'force_metabox_order' ) );
        add_filter( 'hidden_meta_boxes',         array( __CLASS__, 'force_metabox_visible' ), 10, 2 );
        add_action( 'save_post_' . TNC_FLIPBOOK_3D_CPT, array( __CLASS__, 'save_meta' ), 10, 2 );
        add_filter( 'wp_insert_post_data',       array( __CLASS__, 'require_source_to_publish' ), 10, 2 );
        add_action( 'admin_notices',             array( __CLASS__, 'render_source_required_notice' ) );
        add_filter( 'redirect_post_location',    array( __CLASS__, 'persist_active_tab_on_redirect' ), 10, 2 );
        add_action( 'admin_enqueue_scripts',     array( __CLASS__, 'enqueue_assets' ) );

        // Remove default publish metabox for clean sidebar layout
        add_action( 'add_meta_boxes', array( __CLASS__, 'remove_default_boxes' ), 20 );

        // CRUD lifecycle hooks
        add_action( 'wp_trash_post',        array( __CLASS__, 'on_trash' ) );
        add_action( 'before_delete_post',   array( __CLASS__, 'on_delete' ) );
    }

    public static function on_trash( $post_id ) {
        if ( TNC_FLIPBOOK_3D_CPT === get_post_type( $post_id ) ) {
            do_action( 'tncfb3d_flipbook_trashed', $post_id );
        }
    }

    public static function on_delete( $post_id ) {
        if ( TNC_FLIPBOOK_3D_CPT === get_post_type( $post_id ) ) {
            do_action( 'tncfb3d_flipbook_deleted', $post_id );
        }
    }

    // ── Metabox registration ──────────────────────────────────────────────────

    public static function register_metaboxes() {
        // Main wizard
        add_meta_box(
            'tncfb3d_wizard',
            __( 'Flipbook Settings', 'tnc-flipbook-3d-lite' ),
            array( __CLASS__, 'render_wizard' ),
            TNC_FLIPBOOK_3D_CPT,
            'normal',
            'high'
        );

        // Embed & Preview (below wizard, full width)
        add_meta_box(
            'tncfb3d_sidebar',
            __( 'Shortcode Generator', 'tnc-flipbook-3d-lite' ),
            array( __CLASS__, 'render_sidebar' ),
            TNC_FLIPBOOK_3D_CPT,
            'normal',
            'default'
        );

        // Publish box stays in sidebar
        add_meta_box( 'submitdiv', __( 'Publish', 'tnc-flipbook-3d-lite' ), 'post_submit_meta_box', TNC_FLIPBOOK_3D_CPT, 'side', 'high' );
    }

    public static function remove_default_boxes() {
        // We re-add submitdiv ourselves in the correct position
    }

    public static function force_metabox_order( $order ) {
        return array(
            'normal' => 'tncfb3d_wizard,tncfb3d_sidebar',
            'side'   => 'submitdiv',
            'advanced' => '',
        );
    }

    public static function force_metabox_visible( $hidden, $screen ) {
        if ( isset( $screen->post_type ) && TNC_FLIPBOOK_3D_CPT === $screen->post_type ) {
            return array_values( array_diff( (array) $hidden, array( 'tncfb3d_wizard', 'tncfb3d_sidebar' ) ) );
        }
        return $hidden;
    }

    // ── Render callbacks ──────────────────────────────────────────────────────

    public static function render_wizard( $post ) {
        $meta   = self::get_post_meta( $post->ID );
        $schema = TNC_Flipbook_3D_Meta_Schema::get();
        $global = get_option( TNC_FLIPBOOK_3D_OPTION, array() );
        include TNC_FLIPBOOK_3D_DIR . 'admin/views/metabox-wizard.php';
    }

    public static function render_sidebar( $post ) {
        $meta = self::get_post_meta( $post->ID );
        include TNC_FLIPBOOK_3D_DIR . 'admin/views/metabox-sidebar.php';
    }

    // ── Save handler ──────────────────────────────────────────────────────────

    /**
     * Preserve the active metabox tab across the post-update redirect.
     */
    public static function persist_active_tab_on_redirect( $location, $post_id ) {
        if ( get_post_type( $post_id ) !== TNC_FLIPBOOK_3D_CPT ) {
            return $location;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Runs inside core's post-update redirect, after WordPress verified the edit_post nonce; value is sanitized below.
        if ( empty( $_POST['tncfb3d_active_tab'] ) ) {
            return $location;
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- See note above; sanitized via sanitize_key + wp_unslash.
        $tab = sanitize_key( wp_unslash( $_POST['tncfb3d_active_tab'] ) );
        if ( $tab === '' ) {
            return $location;
        }
        return add_query_arg( 'tncfb3d_tab', $tab, $location );
    }

    /**
     * Block publish/future when no source (PDF/multi-PDF/images) is selected.
     * Forces status back to draft and stores a flag to render an admin notice.
     */
    public static function require_source_to_publish( $data, $postarr ) {
        if ( empty( $data['post_type'] ) || TNC_FLIPBOOK_3D_CPT !== $data['post_type'] ) {
            return $data;
        }
        if ( ! in_array( $data['post_status'], array( 'publish', 'future', 'pending' ), true ) ) {
            return $data;
        }
        // Only validate when our metabox was submitted (skip quick-edit/REST/CLI),
        // and verify the nonce before reading any submitted source fields.
        $post_id_for_nonce = isset( $postarr['ID'] ) ? absint( $postarr['ID'] ) : 0;
        if ( empty( $_POST['tncfb3d_meta_nonce'] )
            || ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['tncfb3d_meta_nonce'] ) ), 'tncfb3d_save_meta_' . $post_id_for_nonce ) ) {
            return $data;
        }
        $p          = TNC_FLIPBOOK_3D_PREFIX;
        $source     = isset( $_POST[ $p . 'source_type' ] ) ? sanitize_key( wp_unslash( $_POST[ $p . 'source_type' ] ) ) : 'pdf';
        $has_source = false;
        switch ( $source ) {
            case 'images':
                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- IDs are cast via absint() on the next line.
                $ids        = isset( $_POST[ $p . 'image_ids' ] ) ? (array) wp_unslash( $_POST[ $p . 'image_ids' ] ) : array();
                $has_source = ! empty( array_filter( array_map( 'absint', $ids ) ) );
                break;
            case 'multi-pdf':
                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Only row['id'] presence is read below; no raw value is stored or output.
                $files = isset( $_POST[ $p . 'pdf_files' ] ) ? (array) wp_unslash( $_POST[ $p . 'pdf_files' ] ) : array();
                foreach ( $files as $row ) {
                    if ( is_array( $row ) && ! empty( $row['id'] ) ) { $has_source = true; break; }
                }
                break;
            case 'pdf':
            default:
                $has_source = ! empty( $_POST[ $p . 'pdf_id' ] ) && absint( $_POST[ $p . 'pdf_id' ] ) > 0;
                break;
        }
        if ( ! $has_source ) {
            $data['post_status'] = 'draft';
            $post_id             = isset( $postarr['ID'] ) ? absint( $postarr['ID'] ) : 0;
            if ( $post_id ) {
                set_transient( 'tncfb3d_source_required_' . $post_id, $source, 60 );
            }
        }
        return $data;
    }

    /**
     * Render the "source required" admin notice after a blocked publish attempt.
     */
    public static function render_source_required_notice() {
        global $post;
        if ( ! $post || TNC_FLIPBOOK_3D_CPT !== $post->post_type ) {
            return;
        }
        $key    = 'tncfb3d_source_required_' . $post->ID;
        $source = get_transient( $key );
        if ( false === $source ) {
            return;
        }
        delete_transient( $key );
        $labels = array(
            'pdf'       => __( 'a PDF file', 'tnc-flipbook-3d-lite' ),
            'multi-pdf' => __( 'at least one PDF file', 'tnc-flipbook-3d-lite' ),
            'images'    => __( 'at least one image', 'tnc-flipbook-3d-lite' ),
        );
        $what = isset( $labels[ $source ] ) ? $labels[ $source ] : $labels['pdf'];
        echo '<div class="notice notice-error"><p><strong>' . esc_html__( 'FlipBook not published.', 'tnc-flipbook-3d-lite' ) . '</strong> ';
        printf(
            /* translators: %s: source description (PDF / image / multi-PDF) */
            esc_html__( 'You must add %s in the Content tab before publishing. The flipbook has been saved as a draft.', 'tnc-flipbook-3d-lite' ),
            esc_html( $what )
        );
        echo '</p></div>';
    }

    /**
     * Save all flipbook meta on post save.
     */
    public static function save_meta( $post_id, $post ) {
        // Security checks
        if ( ! isset( $_POST['tncfb3d_meta_nonce'] ) ) {
            return;
        }
        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tncfb3d_meta_nonce'] ) ), 'tncfb3d_save_meta_' . $post_id ) ) {
            return;
        }
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }
        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }

        $is_new = ! metadata_exists( 'post', $post_id, '_tncfb3d_saved' );

        do_action( 'tncfb3d_before_save_meta', $post_id, $post );

        $schema = TNC_Flipbook_3D_Meta_Schema::get();
        $p      = TNC_FLIPBOOK_3D_PREFIX;

        foreach ( $schema as $meta_key => $config ) {
            $short_key = str_replace( $p, '', $meta_key ); // key without prefix

            // Save the override flag (if overridable)
            if ( ! empty( $config['overridable'] ) ) {
                $override_key = $meta_key . '_override';
                $override_val = ! empty( $_POST[ $override_key ] );
                update_post_meta( $post_id, $override_key, $override_val ? '1' : '' );
            }

            // Save the main value
            if ( isset( $_POST[ $meta_key ] ) ) {
                // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized per-field via TNC_Flipbook_3D_Meta_Schema::sanitize() on the next line.
                $raw   = wp_unslash( $_POST[ $meta_key ] );
                $clean = TNC_Flipbook_3D_Meta_Schema::sanitize( $meta_key, $raw );
                update_post_meta( $post_id, $meta_key, $clean );
            } elseif ( 'bool' === $config['type'] ) {
                // Unchecked checkboxes are not submitted - treat as false
                update_post_meta( $post_id, $meta_key, '' );
            } elseif ( 'array' === $config['type'] ) {
                // Empty arrays are not submitted - clear the stored value
                update_post_meta( $post_id, $meta_key, array() );
            }
        }

        do_action( 'tncfb3d_save_meta', $post_id, $post );

        // Auto-update page_count after saving PDFs/images
        self::update_page_count( $post_id );

        update_post_meta( $post_id, '_tncfb3d_saved', '1' );

        if ( $is_new ) {
            do_action( 'tncfb3d_flipbook_created', $post_id );
        } else {
            do_action( 'tncfb3d_flipbook_updated', $post_id );
        }

        do_action( 'tncfb3d_after_save_meta', $post_id, $post );
    }

    // ── Asset enqueue ─────────────────────────────────────────────────────────

    public static function enqueue_assets( $hook ) {
        $screen = get_current_screen();
        if ( ! $screen ) return;

        // Allow flipbook CPT screens AND plugin admin pages (settings, ideas, etc.)
        $is_flipbook_screen = TNC_FLIPBOOK_3D_CPT === $screen->post_type
            || strpos( $screen->id, 'tnc-flipbook-3d-lite' ) !== false;
        if ( ! $is_flipbook_screen ) {
            return;
        }

        // Admin CSS
        wp_enqueue_style(
            'tncfb3d-admin',
            TNC_FLIPBOOK_3D_URL . 'admin/css/tnc-flipbook-3d-admin.css',
            array(),
            TNC_FLIPBOOK_3D_VERSION
        );

        // WordPress media uploader
        wp_enqueue_media();

        // jQuery UI Sortable (for gallery / multi-PDF reorder)
        wp_enqueue_script( 'jquery-ui-sortable' );

        // Admin JS
        wp_enqueue_script(
            'tncfb3d-admin',
            TNC_FLIPBOOK_3D_URL . 'admin/js/tnc-flipbook-3d-admin.js',
            array( 'jquery', 'jquery-ui-sortable', 'wp-util' ),
            TNC_FLIPBOOK_3D_VERSION,
            true
        );

        // Pass data to JS
        $admin_data = array(
            'ajaxUrl'    => admin_url( 'admin-ajax.php' ),
            'nonce'      => wp_create_nonce( 'tncfb3d_admin' ),
            'pluginUrl'  => TNC_FLIPBOOK_3D_URL,
            'strings'    => array(
                'choosePDF'     => __( 'Choose PDF',    'tnc-flipbook-3d-lite' ),
                'chooseImage'   => __( 'Choose Image',  'tnc-flipbook-3d-lite' ),
                'chooseVideo'   => __( 'Choose Video',  'tnc-flipbook-3d-lite' ),
                'usePDF'        => __( 'Use this PDF',  'tnc-flipbook-3d-lite' ),
                'useImage'      => __( 'Use this Image','tnc-flipbook-3d-lite' ),
                'useVideo'      => __( 'Use this Video','tnc-flipbook-3d-lite' ),
                'addImages'     => __( 'Add to Gallery','tnc-flipbook-3d-lite' ),
                'copied'        => __( 'Copied!',       'tnc-flipbook-3d-lite' ),
                'customValue'   => __( 'Custom value',  'tnc-flipbook-3d-lite' ),
                'globalDefault' => __( 'Using global default', 'tnc-flipbook-3d-lite' ),
            ),
        );
        $admin_data = apply_filters( 'tncfb3d_admin_localize_data', $admin_data );
        wp_localize_script( 'tncfb3d-admin', 'tncfb3dAdminData', $admin_data );

        // Hotspot visual editor (Pro only, on single post edit screen)
        if ( function_exists( 'tnc_flipbook_3d_is_pro' ) && tnc_flipbook_3d_is_pro() && 'post' === $screen->base ) {
            wp_enqueue_style(
                'tncfb3d-hotspot-editor',
                TNC_FLIPBOOK_3D_URL . 'admin/css/tnc-flipbook-3d-hotspot-editor.css',
                array(),
                TNC_FLIPBOOK_3D_VERSION
            );
            wp_enqueue_script(
                'tncfb3d-hotspot-editor',
                TNC_FLIPBOOK_3D_URL . 'admin/js/tnc-flipbook-3d-hotspot-editor.js',
                array( 'jquery' ),
                TNC_FLIPBOOK_3D_VERSION,
                true
            );
            wp_localize_script( 'tncfb3d-hotspot-editor', 'tncfb3dHotspotData', array(
                'pdfjsSrc'  => TNC_FLIPBOOK_3D_URL . 'assets/lib/pdf.mjs',
                'workerSrc' => TNC_FLIPBOOK_3D_URL . 'assets/lib/pdf.worker.mjs',
                'pluginUrl' => TNC_FLIPBOOK_3D_URL,
                'icons'     => array( 'pin', 'cart', 'info', 'star', 'tag', 'link', 'play' ),
            ) );
        }

        do_action( 'tncfb3d_admin_enqueue_scripts', $hook, $screen );
    }


    /**
     * Minimal inline CSS for the list table (shortcode column, copy buttons).
     */
    public static function inline_list_table_css() {
        $screen = get_current_screen();
        if ( ! $screen || TNC_FLIPBOOK_3D_CPT !== $screen->post_type ) {
            return;
        }
        // List-table CSS moved to the enqueued admin stylesheet for WordPress.org.
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    /**
     * Fetch all meta for a post, keyed without the prefix.
     */
    public static function get_post_meta( $post_id ) {
        $schema = TNC_Flipbook_3D_Meta_Schema::get();
        $p      = TNC_FLIPBOOK_3D_PREFIX;
        $result = array();

        foreach ( $schema as $meta_key => $config ) {
            $short_key = str_replace( $p, '', $meta_key );
            $raw       = get_post_meta( $post_id, $meta_key, true );

            if ( '' === $raw || false === $raw ) {
                // For booleans, distinguish "never saved" from "saved as unchecked"
                if ( 'bool' === $config['type'] && metadata_exists( 'post', $post_id, $meta_key ) ) {
                    $result[ $short_key ] = false;
                } else {
                    $result[ $short_key ] = $config['default'];
                }
            } else {
                $result[ $short_key ] = $raw;
            }

            if ( ! empty( $config['overridable'] ) ) {
                $override_raw = get_post_meta( $post_id, $meta_key . '_override', true );
                $result[ $short_key . '_override' ] = (bool) $override_raw;
            }
        }

        return $result;
    }

    /**
     * Auto-calculate and cache page count from PDF or image meta.
     * For PDFs we can't easily count pages server-side without a library,
     * so we rely on JS to POST the count via admin-ajax after upload.
     */
    private static function update_page_count( $post_id ) {
        $p    = TNC_FLIPBOOK_3D_PREFIX;
        $type = get_post_meta( $post_id, $p . 'source_type', true );

        if ( 'images' === $type ) {
            $ids = get_post_meta( $post_id, $p . 'image_ids', true );
            if ( is_array( $ids ) ) {
                update_post_meta( $post_id, $p . 'page_count', count( $ids ) );
            }
        } elseif ( 'multi_pdf' === $type ) {
            // Total will be updated by JS after PDF analysis; leave existing value
        }
        // For single PDF, page count is set by JS
    }
}
