<?php
/**
 * Author: Rymera We Co.
 *
 * @package SAAI\Factories
 */

namespace SAAI\Post_Types;

use SAAI\Abstracts\Abstract_Class;
use SAAI\AI_Agents\Product_Questions_AI;
use SAAI\Classes\Product_Question;
use SAAI\Factories\Vite_App;
use SAAI\Helpers\Helper;
use SAAI\Traits\Singleton_Trait;
use WP_Post;

/**
 * Product_Questions class.
 *
 * @since 1.0.0
 */
class Product_Question_Post_Type extends Abstract_Class {

    use Singleton_Trait;

    /**
     * Holds the class instance object
     *
     * @since 1.0.0
     * @var Product_Question_Post_Type $instance object
     */
    protected static $instance;

    /**
     * Register the custom post type.
     *
     * @since 1.0.0
     */
    public function register_post_type() {

        $labels = array(
            'name'               => _x( 'Product Questions', 'post type general name', 'storeagent-ai-for-woocommerce' ),
            'singular_name'      => _x( 'Product Question', 'post type singular name', 'storeagent-ai-for-woocommerce' ),
            'menu_name'          => _x( 'Product Questions', 'admin menu', 'storeagent-ai-for-woocommerce' ),
            'name_admin_bar'     => _x( 'Product Question', 'add new on admin bar', 'storeagent-ai-for-woocommerce' ),
            'add_new'            => _x( 'Add New', 'product question', 'storeagent-ai-for-woocommerce' ),
            'add_new_item'       => __( 'Add New Product Question', 'storeagent-ai-for-woocommerce' ),
            'new_item'           => __( 'New Product Question', 'storeagent-ai-for-woocommerce' ),
            'edit_item'          => __( 'Edit Product Question', 'storeagent-ai-for-woocommerce' ),
            'view_item'          => __( 'View Product Question', 'storeagent-ai-for-woocommerce' ),
            'all_items'          => __( 'Product Questions', 'storeagent-ai-for-woocommerce' ),
            'search_items'       => __( 'Search Product Questions', 'storeagent-ai-for-woocommerce' ),
            'parent_item_colon'  => __( 'Parent Product Questions:', 'storeagent-ai-for-woocommerce' ),
            'not_found'          => __( 'No product questions found.', 'storeagent-ai-for-woocommerce' ),
            'not_found_in_trash' => __( 'No product questions found in Trash.', 'storeagent-ai-for-woocommerce' ),
        );

        $args = array(
            'labels'              => $labels,
            'public'              => false,
            'show_in_rest'        => false,
            'publicly_queryable'  => false,
            'show_ui'             => true,
            'exclude_from_search' => true,
            'show_in_menu'        => 'edit.php?post_type=product',
            'query_var'           => true,
            'rewrite'             => array( 'slug' => Product_Question::POST_TYPE ),
            'capability_type'     => 'post',
            'has_archive'         => false,
            'hierarchical'        => false,
            'menu_position'       => null,
            'supports'            => array( 'title', 'editor' ),
        );

        register_post_type( Product_Question::POST_TYPE, $args );
    }

    /**
     * Add the related product column.
     *
     * @param array $columns The columns.
     *
     * @return mixed
     */
    public function related_product_column( $columns ) {

        $new_columns = array();
        foreach ( $columns as $column_key => $column_value ) {
            $new_columns[ $column_key ] = $column_value;
            if ( 'title' === $column_key ) {
                $new_columns['answer']          = __( 'Answer', 'storeagent-ai-for-woocommerce' );
                $new_columns['related_product'] = __( 'Related Product', 'storeagent-ai-for-woocommerce' );
            }
        }

        return $new_columns;
    }

    /**
     * Render the related product column.
     *
     * @param string $column  The column.
     * @param int    $post_id The post ID.
     *
     * @return void
     */
    public function render_related_product_column( $column, $post_id ) {

        if ( 'related_product' === $column ) {
            $product_id = (int) get_post_meta( $post_id, '_product_id', true );
            if ( $product_id ) {
                $product = wc_get_product( $product_id );
                if ( $product ) {
                    printf(
                        '<a href="%s">%s</a> <small>(<a href="%s">%s</a>)</small>',
                        esc_url( $product->get_permalink() ),
                        esc_html( $product->get_name() ),
                        esc_url( admin_url( 'post.php?post=' . $product_id . '&action=edit' ) ),
                        esc_html(
                            sprintf(/* translators: %d = product id */
                                __( 'ID: %d', 'storeagent-ai-for-woocommerce' ),
                                $product_id
                            )
                        )
                    );
                } else {
                    echo '<span class="deleted-product">' . esc_html__( 'Product deleted', 'storeagent-ai-for-woocommerce' ) . '</span>';
                }
            }
        } elseif ( 'answer' === $column ) {
            $post = get_post( $post_id );
            if ( $post ) {
                $excerpt = wp_trim_words( $post->post_content, 40, '...' );
                echo esc_html( $excerpt );
            }
        }
    }

    /**
     * Enqueue scripts.
     *
     * @param string $hook The hook.
     *
     * @since 1.0.0
     * @return void
     */
    public function admin_enqueue_scripts( $hook ) {

        if ( 'post-new.php' !== $hook && 'post.php' !== $hook ) {
            return;
        }

        if ( Product_Question::POST_TYPE !== get_post_type() && 'product' !== get_post_type() ) {
            return;
        }

        $l10n = array(
            'productsUrl' => rest_url( 'wc/v3/products' ),
            'wpNonce'     => wp_create_nonce( 'wp_rest' ),
        );

        $script = new Vite_App(
            'product-question-screen-script',
            'src/vanilla/admin/product-question/index.ts',
            array( 'select2' ),
            $l10n,
            'saaiObj',
            array( 'woocommerce_admin_styles' )
        );

        $script->enqueue();
    }

    /**
     * Render the related product meta box.
     *
     * @param WP_Post $post The post object.
     *
     * @return void
     */
    public function render_related_product_meta_box( $post ) {

        include_once Helper::locate_admin_template( 'parts/product-question-related-product.php' );
    }

    /**
     * Render the related product meta box.
     *
     * @param WP_Post $post The post object.
     *
     * @return void
     */
    public function add_meta_boxes( $post ) {

        add_meta_box(
            'product_question_related_product',
            __( 'Related Product', 'storeagent-ai-for-woocommerce' ),
            array( $this, 'render_related_product_meta_box' ),
            Product_Question::POST_TYPE,
            'side'
        );
    }

    /**
     * Save the related product.
     *
     * @param int $post_id The post ID.
     *
     * @return void
     */
    public function save_related_product( $post_id ) {

        if ( ! isset( $_POST['saai_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['saai_nonce'] ), 'product-question-related-product' ) ) {
            return;
        }

        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }

        // Get the product ID from POST data (could be empty or invalid).
        $product_id = isset( $_POST['related_product'] ) ? absint( $_POST['related_product'] ) : 0;
        update_post_meta( $post_id, '_product_id', $product_id );

        // Check if trying to publish without a valid related product.
        if ( isset( $_POST['post_status'] ) && 'publish' === $_POST['post_status'] ) {
            if ( ! $this->has_valid_related_product( $post_id ) ) {
                // Force post status back to draft.
                // Remove our own hook to prevent infinite recursion.
                remove_action( 'save_post_' . Product_Question::POST_TYPE, array( $this, 'save_related_product' ) );
                remove_action( 'save_post', 'wp_save_post_revision' );

                wp_update_post(
                    array(
                        'ID'          => $post_id,
                        'post_status' => 'draft',
                    )
                );

                // Re-add the hooks.
                add_action( 'save_post', 'wp_save_post_revision' );
                add_action( 'save_post_' . Product_Question::POST_TYPE, array( $this, 'save_related_product' ) );

                // Set error message for admin notice.
                set_transient( 'saai_product_question_validation_error_' . get_current_user_id(), 'missing_related_product', 30 );
            }
        }
    }

    /**
     * Check if a product question has a valid related product.
     *
     * @param int $post_id The post ID.
     *
     * @return bool
     */
    public function has_valid_related_product( $post_id ) {
        $product_id = (int) get_post_meta( $post_id, '_product_id', true );

        if ( ! $product_id ) {
            return false;
        }

        $product = wc_get_product( $product_id );
        return $product && $product->exists();
    }

    /**
     * Display validation admin notices.
     *
     * @return void
     */
    public function display_validation_admin_notice() {
        $error = get_transient( 'saai_product_question_validation_error_' . get_current_user_id() );

        if ( 'missing_related_product' === $error ) {
            printf(
                '<div class="notice notice-error is-dismissible"><p><strong>%1$s</strong> %2$s</p></div>',
                esc_html__( 'ERROR:', 'storeagent-ai-for-woocommerce' ),
                esc_html__( 'Please select a related product to be associated with this Q&A.', 'storeagent-ai-for-woocommerce' )
            );
            delete_transient( 'saai_product_question_validation_error_' . get_current_user_id() );
        }
    }

    /**
     * Add custom row actions.
     *
     * @param array    $actions Array of actions.
     * @param \WP_Post $post    Post object.
     *
     * @return array
     */
    public function post_row_actions( $actions, $post ) {
        if ( Product_Question::POST_TYPE === $post->post_type && 'publish' !== $post->post_status ) {
            $nonce        = wp_create_nonce( 'approve-question-' . $post->ID );
            $approve_link = admin_url( sprintf( 'admin-post.php?action=approve_question&post_id=%d&_wpnonce=%s', $post->ID, $nonce ) );
            $actions      = array_merge(
                array(
                    'approve-question' => sprintf(
                        '<a href="%s" style="color: #00a32a;" class="approve-question">%s</a>',
                        esc_url( $approve_link ),
                        esc_html__( 'Approve', 'storeagent-ai-for-woocommerce' )
                    ),
                ),
                $actions
            );
        }
        return $actions;
    }

    /**
     * Handle the approve action.
     *
     * @return void
     */
    public function handle_approve_action() {
        if ( ! isset( $_GET['post_id'] ) || ! isset( $_GET['_wpnonce'] ) ) {
            return;
        }

        $post_id = intval( $_GET['post_id'] );
        $nonce   = sanitize_key( $_GET['_wpnonce'] );

        if ( ! wp_verify_nonce( $nonce, 'approve-question-' . $post_id ) ) {
            wp_die( esc_html__( 'Invalid nonce', 'storeagent-ai-for-woocommerce' ) );
        }

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            wp_die( esc_html__( 'You do not have permission to approve questions', 'storeagent-ai-for-woocommerce' ) );
        }

        $post = get_post( $post_id );
        if ( ! $post || Product_Question::POST_TYPE !== $post->post_type ) {
            wp_die( esc_html__( 'Invalid question', 'storeagent-ai-for-woocommerce' ) );
        }

        // Check if has valid related product before approving.
        if ( ! $this->has_valid_related_product( $post_id ) ) {
            set_transient( 'saai_product_question_validation_error_' . get_current_user_id(), 'missing_related_product', 30 );
            wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'edit.php?post_type=' . Product_Question::POST_TYPE ) );
            exit;
        }

        wp_update_post(
            array(
                'ID'          => $post_id,
                'post_status' => 'publish',
            )
        );

        wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'edit.php?post_type=' . Product_Question::POST_TYPE ) );
        exit;
    }

    /**
     * Add bulk actions.
     *
     * @param array $bulk_actions Array of bulk actions.
     *
     * @return array
     */
    public function register_bulk_actions( $bulk_actions ) {
        $bulk_actions = array_merge( array( 'approve_questions' => __( 'Approve', 'storeagent-ai-for-woocommerce' ) ), $bulk_actions );
        return $bulk_actions;
    }

    /**
     * Handle bulk actions.
     *
     * @param string $redirect_url The redirect URL.
     * @param string $action       The action being taken.
     * @param array  $post_ids     The posts IDs.
     *
     * @return string
     */
    public function handle_bulk_actions( $redirect_url, $action, $post_ids ) {
        if ( 'approve_questions' === $action ) {
            $approved = 0;
            $skipped  = 0;

            foreach ( $post_ids as $post_id ) {
                $post = get_post( $post_id );

                if ( ! $post || Product_Question::POST_TYPE !== $post->post_type ) {
                    continue;
                }

                if ( ! current_user_can( 'edit_post', $post_id ) ) {
                    continue;
                }

                if ( 'publish' === $post->post_status ) {
                    continue;
                }

                // Check if has valid related product before approving.
                if ( ! $this->has_valid_related_product( $post_id ) ) {
                    ++$skipped;
                    continue;
                }

                wp_update_post(
                    array(
                        'ID'          => $post_id,
                        'post_status' => 'publish',
                    )
                );

                ++$approved;
            }

            $redirect_url = add_query_arg(
                array(
                    'approved' => $approved,
                    'skipped'  => $skipped,
                    'ids'      => join( ',', $post_ids ),
                ),
                $redirect_url
            );
        }

        return $redirect_url;
    }

    /**
     * Display admin notices for bulk actions.
     *
     * @return void
     */
    public function bulk_action_admin_notice() {
        if ( ! empty( $_REQUEST['approved'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $approved_count = intval( $_REQUEST['approved'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $skipped_count  = isset( $_REQUEST['skipped'] ) ? intval( $_REQUEST['skipped'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

            if ( $approved_count > 0 ) {
                printf(
                    '<div class="updated notice is-dismissible"><p>' .
                    /* translators: %d: number of questions */
                    esc_html( _n( '%d question approved.', '%d questions approved.', $approved_count, 'storeagent-ai-for-woocommerce' ) ) .
                    '</p></div>',
                    esc_html( $approved_count )
                );
            }

            if ( $skipped_count > 0 ) {
                printf(
                    '<div class="notice notice-warning is-dismissible"><p>' .
                    /* translators: %d: number of questions */
                    esc_html( _n( '%d question was skipped because it does not have a related product selected.', '%d questions were skipped because they do not have a related product selected.', $skipped_count, 'storeagent-ai-for-woocommerce' ) ) .
                    '</p></div>',
                    esc_html( $skipped_count )
                );
            }
        }
    }

    /**
     * Run hooks for the class.
     */
    public function run() {

        if ( ! Product_Questions_AI::instance()->is_enabled() ) {
            return;
        }

        add_action( 'init', array( $this, 'register_post_type' ) );
        add_filter( 'manage_' . Product_Question::POST_TYPE . '_posts_columns', array( $this, 'related_product_column' ) );
        add_action( 'manage_' . Product_Question::POST_TYPE . '_posts_custom_column', array( $this, 'render_related_product_column' ), 10, 2 );
        add_action( 'add_meta_boxes_' . Product_Question::POST_TYPE, array( $this, 'add_meta_boxes' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
        add_action( 'save_post_' . Product_Question::POST_TYPE, array( $this, 'save_related_product' ) );
        add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 );
        add_action( 'admin_post_approve_question', array( $this, 'handle_approve_action' ) );
        add_action( 'admin_notices', array( $this, 'display_validation_admin_notice' ) );

        // Add bulk action hooks.
        add_filter( 'bulk_actions-edit-' . Product_Question::POST_TYPE, array( $this, 'register_bulk_actions' ) );
        add_filter( 'handle_bulk_actions-edit-' . Product_Question::POST_TYPE, array( $this, 'handle_bulk_actions' ), 10, 3 );
        add_action( 'admin_notices', array( $this, 'bulk_action_admin_notice' ) );
    }
}
