<?php

/**
 * Front End action, hooks and other stuff here
 *
 * @package EASYFUA
 */
// Prevent direct access.
defined( 'ABSPATH' ) || exit;
/**
 * Main frontend class mostly handle hooks, enque, and uploader html preview.
 */
final class EASYFUA_Frontend {
    /**
     * Security nonce name
     *
     * @var string
     */
    const NONCE_NAME = 'easyfua-security-nonce';

    /**
     * Front-end constructor load for includes, inits and hooks.
     */
    public function __construct() {
        $this->includes();
        $this->init();
        $this->hooks();
    }

    /**
     * Includes front-end stuff or need file here.
     *
     * @return void
     */
    public function includes() {
        // Core handlers for file operations and approval logic.
        if ( defined( 'EASYFUA_PLUGIN_DIR_INC' ) ) {
            require_once EASYFUA_PLUGIN_DIR_INC . 'front-end/class-easyfua-file-handler.php';
        }
    }

    /**
     * Init class or functions
     *
     * @return void
     */
    public function init() {
        new EASYFUA_File_Handler();
    }

    /**
     * All front end hooks goes here
     *
     * @return void
     */
    public function hooks() {
        add_action( 'wp_enqueue_scripts', array($this, 'enqueue') );
        add_filter( 'the_content', array($this, 'show_uploader') );
        add_filter(
            'upload_mimes',
            array($this, 'mime_types'),
            1,
            1
        );
        /* Shortcode */
        add_shortcode( 'easyfua_upload', array($this, 'display_uploader') );
        /* Blocks */
        add_action( 'init', array($this, 'register_blocks') );
        add_action( 'enqueue_block_editor_assets', array($this, 'register_blocks_css') );
        /* Cron - Schedule to delete temporary files */
        add_action( 'easyfua_delete_temp_files', array($this, 'clean_up_temp_files') );
        /* Handle nonce creation */
        add_action( 'wp_ajax_easyfua_rest_nonce', array($this, 'create_nonce') );
        add_action( 'wp_ajax_nopriv_easyfua_rest_nonce', array($this, 'create_nonce') );
        /* Prevent Multiple Submission. */
        add_filter( 'easyfua_submission_errors', array($this, 'check_submission') );
    }

    /**
     * Enqueue script like js and css (main plugin assets).
     *
     * @return void
     */
    public function enqueue() {
        global $post;
        // Bail early if not WP_Post.
        if ( !$post instanceof WP_Post ) {
            return;
        }
        // Assets flag.
        $load_assets = false;
        // Only load js on page that has easyfua_upload shortcode.
        if ( isset( $post->post_content ) && has_shortcode( $post->post_content, 'easyfua_upload' ) ) {
            $load_assets = true;
        }
        // Only load js on page that has easy file upload blocks.
        if ( has_block( 'easy-file-upload-approval/easyfua-block', $post ) ) {
            $load_assets = true;
        }
        // Show uploader to match the specific ID.
        if ( isset( $post->ID ) && absint( easyfua_settings( 'display_on' ) ) === $post->ID ) {
            $load_assets = true;
        }
        // Check if we load the assets.
        if ( !$load_assets ) {
            return;
        }
        // Enqueue script and style.
        if ( easyfua_is_premium() ) {
            wp_enqueue_script(
                'easyfua-public',
                EASYFUA_PLUGIN_URL . 'public/js/easyfua__premium_only.js',
                array('jquery'),
                EASYFUA_VERSION,
                true
            );
        } else {
            wp_enqueue_script(
                'easyfua-public',
                EASYFUA_PLUGIN_URL . 'public/js/easyfua.js',
                array(),
                EASYFUA_VERSION,
                true
            );
        }
        wp_enqueue_style(
            'easyfua-public',
            EASYFUA_PLUGIN_URL . 'public/css/easyfua.css',
            array(),
            EASYFUA_VERSION
        );
        // Enqueue recaptcha script.
        $site_key = easyfua_settings( 'site_key' );
        if ( !empty( $site_key ) ) {
            wp_enqueue_script(
                'easyfua-google-recaptcha',
                'https://www.google.com/recaptcha/api.js?render=' . $site_key,
                array(),
                1.0,
                true
            );
        }
        // All data options.
        $data_options = apply_filters( 'easyfua_data_options', array(
            'tag'              => 'span',
            'text'             => ( easyfua_settings( 'text' ) ? esc_html( easyfua_settings( 'text' ) ) : esc_html__( 'Drag & Drop Files Here', 'easy-file-upload-approval' ) ),
            'or_separator'     => ( easyfua_settings( 'or' ) ? esc_html( easyfua_settings( 'or' ) ) : esc_html__( 'or', 'easy-file-upload-approval' ) ),
            'browse'           => ( easyfua_settings( 'browse' ) ? esc_html( easyfua_settings( 'browse' ) ) : esc_html__( 'Browse Files', 'easy-file-upload-approval' ) ),
            'server_max_error' => ( easyfua_settings( 'error_server_limit' ) ? esc_html( easyfua_settings( 'error_server_limit' ) ) : easyfua_error( 'server_limit' ) ),
            'large_file'       => ( easyfua_settings( 'error_files_too_large' ) ? esc_html( easyfua_settings( 'error_files_too_large' ) ) : easyfua_error( 'large_file' ) ),
            'invalid_type'     => ( easyfua_settings( 'error_invalid_file' ) ? esc_html( easyfua_settings( 'error_invalid_file' ) ) : easyfua_error( 'invalid_type' ) ),
            'max_file_limit'   => ( easyfua_settings( 'error_max_file' ) ? esc_html( easyfua_settings( 'error_max_file' ) ) : easyfua_error( 'max_file_limit' ) ),
            'required'         => ( easyfua_settings( 'error_required' ) ? esc_html( easyfua_settings( 'error_required' ) ) : easyfua_error( 'required' ) ),
            'delete'           => array(
                'text'  => esc_html__( 'Deleting', 'easy-file-upload-approval' ),
                'title' => esc_html__( 'Remove', 'easy-file-upload-approval' ),
            ),
            'parallel_uploads' => ( easyfua_settings( 'parallel_uploads' ) ? esc_html( easyfua_settings( 'parallel_uploads' ) ) : 2 ),
            'chunks'           => ( easyfua_settings( 'chunks_upload' ) ? true : false ),
            'chunk_size'       => ( easyfua_settings( 'chunk_size' ) ? easyfua_settings( 'chunk_size' ) : 5000 ),
            'max_total_size'   => ( easyfua_settings( 'max_total_size' ) ? easyfua_settings( 'max_total_size' ) : '100MB' ),
            'err_message'      => array(
                'maxNumFiles'  => ( easyfua_settings( 'error_max_files' ) ? easyfua_settings( 'error_max_files' ) : easyfua_error( 'maxNumFiles' ) ),
                'maxTotalSize' => ( easyfua_settings( 'error_size_limit' ) ? easyfua_settings( 'error_size_limit' ) : easyfua_error( 'maxTotalSize' ) ),
            ),
        ) );
        // registered script with data for a JavaScript variable.
        wp_localize_script( 'easyfua-public', 'easyfua_uploader', array(
            'ajax_url'           => apply_filters( 'easyfua_ajax_url', admin_url( 'admin-ajax.php' ) ),
            'ajax_nonce'         => wp_create_nonce( self::NONCE_NAME ),
            'rest_nonce'         => wp_create_nonce( 'wp_rest' ),
            'drag_n_drop_upload' => $data_options,
            'dnd_text_counter'   => esc_html__( 'of', 'easy-file-upload-approval' ),
            'disable_btn'        => true,
            'rest_api'           => esc_url_raw( rest_url( EASYFUA_PLUGIN_NAME . '/v1/' ) ),
            'g_site_key'         => $site_key,
            'is_pro'             => ( easyfua_is_premium() ? true : false ),
            'storage_type'       => 'local_storage',
            'image_preview'      => ( easyfua_settings( 'image_preview' ) === 'yes' ? true : false ),
        ) );
    }

    /**
     * Add error to limit user submission to 60 seconds
     *
     * @param mixed $errors Containing all the errors from submission.
     */
    public function check_submission( $errors ) {
        $cookie_time_name = 'easyfua_last_submission';
        $cooldown_seconds = MINUTE_IN_SECONDS;
        // 1 minute cooldown.
        $current_time = time();
        // 🕒 Spam prevention: no submissions within 60 seconds.
        if ( isset( $_COOKIE[$cookie_time_name] ) && empty( $errors ) ) {
            $last_time = (int) $_COOKIE[$cookie_time_name];
            $elapsed = $current_time - $last_time;
            if ( $elapsed < $cooldown_seconds ) {
                $remaining = $cooldown_seconds - $elapsed;
                $errors[] = array(
                    'global' => sprintf( 
                        /* translators: %d: remaining seconds */
                        esc_html__( 'Please wait %d seconds before submitting again.', 'easy-file-upload-approval' ),
                        (int) $remaining
                     ),
                );
                return $errors;
            }
        }
        // Update submission cookie for tracking.
        if ( empty( $errors ) ) {
            setcookie(
                $cookie_time_name,
                (string) $current_time,
                $current_time + HOUR_IN_SECONDS,
                COOKIEPATH,
                COOKIE_DOMAIN,
                is_ssl(),
                true
            );
        }
        // Return all the errors.
        return $errors;
    }

    /**
     * Creating new nonce via ajax request.
     *
     * @return void
     */
    public function create_nonce() {
        $origin = ( isset( $_SERVER['HTTP_SEC_FETCH_SITE'] ) ? sanitize_key( wp_unslash( $_SERVER['HTTP_SEC_FETCH_SITE'] ) ) : '' );
        $referer = ( isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '' );
        $user_agent = ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_key( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '' );
        $site = get_site_url();
        // Check for origin.
        if ( empty( $origin ) || !in_array( trim( $origin ), array('same-origin', 'same-site'), true ) ) {
            wp_send_json_error( esc_html__( 'Invalid origin.', 'easy-file-upload-approval' ) );
        }
        // Check for referer.
        if ( empty( $referer ) || strpos( $referer, $site ) !== 0 ) {
            wp_send_json_error( esc_html__( 'Invalid referer.', 'easy-file-upload-approval' ) );
        }
        // Validate User-Agent if it's a browser or device.
        if ( empty( $user_agent ) || preg_match( '/(curl|httpclient|postman|python|wget|node)/i', $user_agent ) || empty( $_COOKIE ) ) {
            wp_send_json_error( esc_html__( 'Invalid client.', 'easy-file-upload-approval' ) );
        }
        // Generate a nonce.
        wp_send_json_success( array(
            'ajax'       => wp_create_nonce( self::NONCE_NAME ),
            'rest_nonce' => wp_create_nonce( 'wp_rest' ),
        ) );
    }

    /**
     * Show uploader based on the selected page in the settings.
     *
     * @param string $content Page content.
     */
    public function show_uploader( $content ) {
        // If not page or already has shortcode bail early.
        if ( !is_singular() || has_shortcode( $content, 'easyfua_upload' ) ) {
            return $content;
        }
        // Check for blocks.
        if ( has_block( 'wp-easy-file-upload-approval/easyfua-block' ) ) {
            return $content;
        }
        // Get page id from the settings.
        $page_id = easyfua_settings( 'display_on' );
        // Show uploader to match the specific ID.
        if ( $page_id && get_the_ID() === absint( $page_id ) ) {
            $uploader = $this->display_uploader();
            // Show uploader before or after.
            $show_before = apply_filters( 'easyfua_show_before', false );
            if ( $show_before ) {
                return $uploader . $content;
            }
            // Show after.
            return $content . $uploader;
        }
        return $content;
    }

    /**
     * Display File Upload UI and Container using shortcode.
     *
     * @param array  $atts    Shortcode attributes.
     * @param string $content Page content.
     */
    public function display_uploader( $atts = '', $content = '' ) {
        // Get custom attributes.
        $atts = easyfua_attributes();
        // Loop attributes.
        $html_attributes = array();
        foreach ( $atts as $id => $attr ) {
            $html_attributes[] = sprintf( '%s="%s"', esc_attr( $id ), esc_attr( $attr ) );
        }
        ob_start();
        ?>
		<form action="" method="POST" enctype="multipart/form-data" id="easyfua-form">
			<input type="hidden" name="easyfua_hp">
			<?php 
        // Name user field.
        if ( 'yes' !== easyfua_settings( 'hide_name_field' ) ) {
            $name_label = ( easyfua_settings( 'name_label' ) ? easyfua_settings( 'name_label' ) : esc_html__( 'Name', 'easy-file-upload-approval' ) );
            printf( '<div class="easyfua-field">
						<label for="easyfua-name">%s:</label>
						<input type="text" id="easyfua-name" class="easyfua_name" name="easyfua_name">
					</div>', esc_html( $name_label ) );
        }
        // Email user field.
        if ( 'yes' !== easyfua_settings( 'hide_email_field' ) ) {
            $email_label = ( easyfua_settings( 'email_label' ) ? easyfua_settings( 'email_label' ) : esc_html__( 'Email Address', 'easy-file-upload-approval' ) );
            printf( '<div class="easyfua-field">
						<label for="easyfua-email">%s:</label>
						<input type="email" id="easyfua-email" class="easyfua_email" name="easyfua_email">
					</div>', esc_html( $email_label ) );
        }
        // Uploader display field.
        printf( '<div class="easyfua-field">
					<label for="easyfua-uploader">%s:</label>
					<input type="file" id="easyfua-uploader" class="easyfua_uploader" multiple %s>
				</div>', ( easyfua_settings( 'label' ) ? esc_html( easyfua_settings( 'label' ) ) : esc_html__( 'Upload Files', 'easy-file-upload-approval' ) ), wp_kses_post( implode( ' ', $html_attributes ) ) );
        printf( '<div class="easyfua-submit-field">
					<button id="easyfua-submit" class="easyfua-submit" type="submit">%s</button>
					<div class="easyfua-loader">
						<svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="4" /></svg>
					</div>
				</div>', ( easyfua_settings( 'button_text' ) ? esc_html( easyfua_settings( 'button_text' ) ) : esc_html__( 'Submit', 'easy-file-upload-approval' ) ) );
        ?>
		</form>
		<?php 
        return ob_get_clean();
    }

    /**
     * Register custom mime types
     *
     * @param mixed $mime_types WordPress default mime types list.
     */
    public function mime_types( $mime_types ) {
        $mimes = trim( easyfua_settings( 'mime_types' ) );
        if ( strpos( $mimes, '|' ) !== false ) {
            $mime_list = explode( "\n", $mimes );
            foreach ( $mime_list as $mime ) {
                list( $ext, $type ) = array_map( 'trim', explode( '|', $mime ) );
                if ( !isset( $mime_types[$ext] ) ) {
                    $mime_types[esc_attr( $ext )] = esc_html( trim( $type ) );
                }
            }
        }
        $mime_types['xls'] = 'application/excel, application/vnd.ms-excel, application/x-excel, application/x-msexcel';
        $mime_types['xlsx'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        return $mime_types;
    }

    /**
     * Init for gutenberg block registration.
     *
     * @return void
     */
    public function register_blocks() {
        // Exit if gutenberg is not active.
        if ( !function_exists( 'register_block_type' ) ) {
            return;
        }
        // Register the script for the block editor.
        $block_js = EASYFUA_PLUGIN_URL . 'public/blocks/easyfua/dist/index.build.js';
        wp_register_script(
            'easyfua-block',
            $block_js,
            array(
                'wp-blocks',
                'wp-element',
                'wp-editor',
                'wp-components'
            ),
            filemtime( EASYFUA_PLUGIN_DIR . 'public/blocks/easyfua/dist/index.build.js' ),
            true
        );
        // Localize text.
        wp_localize_script( 'easyfua-block', 'easyfua_text', array(
            'uploadText' => ( easyfua_settings( 'text' ) ? esc_html( easyfua_settings( 'text' ) ) : esc_html__( 'Drag & Drop Files Here', 'easy-file-upload-approval' ) ),
            'or'         => ( easyfua_settings( 'or' ) ? esc_html( easyfua_settings( 'or' ) ) : esc_html__( 'or', 'easy-file-upload-approval' ) ),
            'browse'     => ( easyfua_settings( 'browse' ) ? esc_html( easyfua_settings( 'browse' ) ) : esc_html__( 'Browse Files', 'easy-file-upload-approval' ) ),
        ) );
        // Register the block type.
        register_block_type( 'easy-file-upload-approval/easyfua-block', array(
            'editor_script'   => 'easyfua-block',
            'render_callback' => array($this, 'render_html_block'),
        ) );
    }

    /**
     * Render HTML blocks in the front-end.
     *
     * @param mixed $attributes  HTML attributes.
     * @return bool|string
     */
    public function render_html_block( $attributes ) {
        return $this->display_uploader();
    }

    /**
     * Enqueue style for admin preview of drag & drop file upload.
     *
     * @return void
     */
    public function register_blocks_css() {
        wp_enqueue_style(
            'easyfua-block-editor',
            EASYFUA_PLUGIN_URL . 'public/blocks/easyfua/style.css',
            array('wp-edit-blocks'),
            '1.0.0'
        );
    }

    /**
     * Delete temporary files based on the time specified in the admin
     * Default is temp file will be deleted 24 hours if not submitted.
     *
     * @return void
     */
    public function clean_up_temp_files() {
        global $wpdb;
        // Getting the temp_hours from the settings or 24hours is the default.
        $hours = ( easyfua_settings( 'delete_temp_hours' ) ? (int) easyfua_settings( 'delete_temp_hours' ) : 24 );
        // Cache data.
        $cache_key = 'easyfua_temp_files';
        $results = wp_cache_get( $cache_key );
        /**
         * example:
         * 2025-10-18 08:00:00 AM = NOW()          (current_time)
         * 2025-10-17 07:00:00 AM = `submitted_at` (24 hours ago)
         * Oct17 7am < Oct18 8am = true [7 < 8]
         * `submitted_at` < 2025-10-18 08:00:00 (behind 24 hours ago)
         */
        if ( false === $results ) {
            $results = $wpdb->get_results( $wpdb->prepare( "SELECT id, file_url, submitted_at\n\t\t\t\t\tFROM {$wpdb->prefix}easyfua_files\n\t\t\t\t\tWHERE file_status = %s\n\t\t\t\t\tAND submitted_at < ( NOW() - INTERVAL %d HOUR )", 'temp', $hours ) );
            // Set the cache.
            wp_cache_set(
                $cache_key,
                $results,
                '',
                1800
            );
            // cache for 30 minutes.
        }
        if ( empty( $results ) ) {
            return;
        }
        // Loop results.
        foreach ( $results as $file ) {
            if ( easyfua_safe_to_delete( $file->file_url ) ) {
                $wpdb->delete( $wpdb->prefix . 'easyfua_files', array(
                    'id' => $file->id,
                ), array('%d') );
            }
        }
    }

}
