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

class PufferGo_Product_CPT {

    const CPT_SLUG = 'puffergo_product';
    const TAX_SLUG = 'puffergo_product_cat';

    public function __construct() {
        add_action( 'init', array( $this, 'register_cpt' ) );
        add_action( 'init', array( $this, 'register_taxonomy' ) );
        add_action( 'init', array( $this, 'register_meta_fields' ) );
        add_action( 'init', array( $this, 'maybe_flush_rewrite_rules' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );
        add_filter( 'rank_math/snippet/rich_snippet_product_entity_types', array( $this, 'rank_math_product_schema' ) );
        add_action( 'admin_init', array( $this, 'register_permalink_settings' ) );
        add_action( 'admin_init', array( $this, 'migrate_gallery_format' ) );
        add_action( 'transition_post_status', array( $this, 'on_first_product_publish' ), 10, 3 );
    }

    /**
     * Get the product category rewrite slug (option value or default).
     */
    public static function get_category_slug() {
        return get_option( 'puffergo_product_category_slug', 'catalog' );
    }

    /**
     * Add PufferGo permalink settings to WordPress Settings > Permalinks page.
     */
    public function register_permalink_settings() {
        add_settings_section(
            'puffergo-permalink',
            __( 'PufferGo Product Permalinks', 'puffergo' ),
            array( $this, 'render_permalink_section_desc' ),
            'permalink'
        );

        add_settings_field(
            'puffergo_product_category_slug',
            __( 'Product category base', 'puffergo' ),
            array( $this, 'render_category_slug_field' ),
            'permalink',
            'puffergo-permalink'
        );

        // Handle save on the permalinks page.
        if ( isset( $_POST['puffergo_permalinks_nonce'] ) ) {
            $this->save_permalink_settings();
        }
    }

    /**
     * Render the section description.
     */
    public function render_permalink_section_desc() {
        esc_html_e( 'Customize the URL structure for PufferGo products.', 'puffergo' );
    }

    /**
     * Render the category slug input field.
     */
    public function render_category_slug_field() {
        $slug = self::get_category_slug();
        ?>
        <input
            type="text"
            name="puffergo_product_category_slug"
            value="<?php echo esc_attr( $slug ); ?>"
            class="regular-text code"
            placeholder="catalog"
        />
        <p class="description">
            <?php
            printf(
                /* translators: %s: example URL slug */
                esc_html__( 'URL prefix for product category archives, e.g. %s', 'puffergo' ),
                '<code>/' . esc_html( $slug ) . '/electronics/</code>'
            );
            ?>
        </p>
        <?php
        wp_nonce_field( 'puffergo_permalinks', 'puffergo_permalinks_nonce' );
    }

    /**
     * Save permalink settings and flush rewrite rules.
     */
    private function save_permalink_settings() {
        check_admin_referer( 'puffergo_permalinks', 'puffergo_permalinks_nonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }

        $new_slug = isset( $_POST['puffergo_product_category_slug'] )
            ? sanitize_title( wp_unslash( $_POST['puffergo_product_category_slug'] ) )
            : '';

        $slug = ! empty( $new_slug ) ? $new_slug : 'catalog';

        // Warn if conflicting with WooCommerce.
        if ( class_exists( 'WooCommerce' ) ) {
            $woo_permalinks = get_option( 'woocommerce_permalinks', array() );
            $woo_cat_slug   = ! empty( $woo_permalinks['category_base'] )
                ? untrailingslashit( $woo_permalinks['category_base'] )
                : 'product-category';

            if ( $slug === $woo_cat_slug ) {
                add_settings_error(
                    'puffergo_permalinks',
                    'conflict',
                    sprintf(
                        /* translators: %s: the conflicting slug */
                        __( '"%s" is already used by WooCommerce product categories. Please choose a different slug.', 'puffergo' ),
                        esc_html( $slug )
                    ),
                    'error'
                );
                return;
            }
        }

        update_option( 'puffergo_product_category_slug', $slug );
        flush_rewrite_rules();
    }

    public function maybe_flush_rewrite_rules() {
        $hash = md5( self::get_category_slug() );
        if ( get_option( 'puffergo_rewrite_hash' ) !== $hash ) {
            flush_rewrite_rules();
            update_option( 'puffergo_rewrite_hash', $hash );
        }
    }

    /**
     * Register front-end assets for product templates.
     */
    public function register_assets() {
        $plugin_url = plugin_dir_url( dirname( __FILE__ ) );
        wp_register_script(
            'puffergo-product-gallery',
            $plugin_url . 'assets/js/puffergo-product-gallery.js',
            array(),
            '1.0.0',
            true
        );
    }

    public function register_cpt() {
        $labels = array(
            'name'               => __( 'Products', 'puffergo' ),
            'singular_name'      => __( 'Product', 'puffergo' ),
            'menu_name'          => __( 'Products', 'puffergo' ),
            'all_items'          => __( 'All Products', 'puffergo' ),
            'add_new'            => __( 'Add New', 'puffergo' ),
            'add_new_item'       => __( 'Add New Product', 'puffergo' ),
            'edit_item'          => __( 'Edit Product', 'puffergo' ),
            'new_item'           => __( 'New Product', 'puffergo' ),
            'view_item'          => __( 'View Product', 'puffergo' ),
            'search_items'       => __( 'Search Products', 'puffergo' ),
            'not_found'          => __( 'No products found', 'puffergo' ),
            'not_found_in_trash' => __( 'No products found in Trash', 'puffergo' ),
        );

        $args = array(
            'labels'             => $labels,
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'menu_position'      => 4,
            'menu_icon'          => 'dashicons-products',
            'query_var'          => true,
            'rewrite'            => array( 'slug' => 'products', 'with_front' => false ),
            'capability_type'    => 'post',
            'has_archive'        => true,
            'hierarchical'       => false,
            'supports'           => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ),
            'show_in_rest'       => true,
        );

        register_post_type( self::CPT_SLUG, $args );
    }

    public function register_taxonomy() {
        $labels = array(
            'name'              => __( 'Product Categories', 'puffergo' ),
            'singular_name'     => __( 'Product Category', 'puffergo' ),
            'search_items'      => __( 'Search Categories', 'puffergo' ),
            'all_items'         => __( 'Categories', 'puffergo' ),
            'parent_item'       => __( 'Parent Category', 'puffergo' ),
            'parent_item_colon' => __( 'Parent Category:', 'puffergo' ),
            'edit_item'         => __( 'Edit Category', 'puffergo' ),
            'update_item'       => __( 'Update Category', 'puffergo' ),
            'add_new_item'      => __( 'Add New Category', 'puffergo' ),
            'new_item_name'     => __( 'New Category Name', 'puffergo' ),
            'menu_name'         => __( 'Categories', 'puffergo' ),
        );

        $args = array(
            'hierarchical'      => true,
            'labels'            => $labels,
            'show_ui'           => true,
            'show_in_menu'      => true,
            'show_admin_column' => true,
            'query_var'         => true,
            'rewrite'           => array( 'slug' => self::get_category_slug(), 'with_front' => false, 'hierarchical' => true ),
            'show_in_rest'      => true,
        );

        register_taxonomy( self::TAX_SLUG, array( self::CPT_SLUG ), $args );
    }

    public function register_meta_fields() {
        $meta_fields = array(
            '_puffergo_price'        => array(
                'type'              => 'string',
                'description'       => __( 'Product Price (JSON)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_moq'          => array(
                'type'              => 'string',
                'description'       => __( 'Minimum Order Quantity (JSON)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_lead_time'    => array(
                'type'              => 'string',
                'description'       => __( 'Lead Time (JSON)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_brochure_url' => array(
                'type'              => 'string',
                'description'       => __( 'Brochure PDF URL', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => 'esc_url_raw',
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_gallery'      => array(
                'type'              => 'string',
                'description'       => __( 'Product Gallery Items (Images, Videos, URLs)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_specs'             => array(
                'type'              => 'string',
                'description'       => __( 'Product Specifications', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_short_description' => array(
                'type'              => 'string',
                'description'       => __( 'Product Short Description', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => 'sanitize_textarea_field',
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_contact_form' => array(
                'type'              => 'string',
                'description'       => __( 'Contact Form Configuration (JSON)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
            '_puffergo_cta_button' => array(
                'type'              => 'string',
                'description'       => __( 'CTA Button Configuration (JSON)', 'puffergo' ),
                'single'            => true,
                'show_in_rest'      => true,
                'sanitize_callback' => array( $this, 'sanitize_json_field' ),
                'auth_callback'     => array( $this, 'auth_callback' ),
            ),
        );

        foreach ( $meta_fields as $meta_key => $args ) {
            register_post_meta( self::CPT_SLUG, $meta_key, $args );
        }
    }

    /**
     * Normalize gallery raw JSON into a uniform array of items.
     *
     * Each item must be an array with a 'type' key:
     *   - ['type' => 'image', 'id' => int]
     *   - ['type' => 'video', 'id' => int, 'poster' => int]
     *   - ['type' => 'url', 'src' => string, 'poster' => int]
     *
     * @param string|null $gallery_raw  Raw _puffergo_gallery meta value.
     * @return array  Normalized gallery items.
     */
    public static function normalize_gallery( $gallery_raw ) {
        $items = $gallery_raw ? json_decode( $gallery_raw, true ) : array();
        if ( ! is_array( $items ) ) {
            return array();
        }
        return array_filter( $items, function( $item ) {
            return is_array( $item ) && isset( $item['type'] );
        });
    }

    /**
     * Normalize specs JSON, ensuring SKU is always the first item.
     *
     * @param string|null $specs_raw  Raw _puffergo_specs meta value.
     * @return array  Normalized specs with SKU first.
     */
    public static function normalize_specs( $specs_raw ) {
        $specs = $specs_raw ? json_decode( $specs_raw, true ) : array();
        if ( ! is_array( $specs ) ) {
            $specs = array();
        }
        if ( empty( $specs ) || ( isset( $specs[0]['key'] ) && $specs[0]['key'] !== 'SKU' ) ) {
            $specs = array_merge(
                array( array( 'key' => 'SKU', 'value' => '' ) ),
                array_filter( $specs, function( $s ) {
                    return isset( $s['key'] ) && $s['key'] !== 'SKU';
                } )
            );
        }
        return $specs;
    }

    /**
     * Get the card display image data for a product (archive / card views).
     *
     * Uses the first gallery item; falls back to featured image.
     * For video items, returns the poster image if set.
     *
     * @param int $product_id  Product post ID.
     * @return array {
     *     @type int    $display_id  Attachment ID to render.
     *     @type bool   $is_video    Whether the item is a video/url type.
     *     @type int    $image_id    Original media ID (video source or image).
     *     @type string $video_src   Video URL for video/url items.
     * }
     */
    public static function get_card_image( $product_id ) {
        $gallery_raw   = get_post_meta( $product_id, '_puffergo_gallery', true );
        $gallery_items = self::normalize_gallery( $gallery_raw );
        $first_item    = ! empty( $gallery_items ) ? $gallery_items[0] : null;

        $image_id   = 0;
        $is_video   = false;
        $poster_id  = 0;
        $video_src  = '';

        if ( $first_item ) {
            $image_id = $first_item['id'] ?? 0;
            $is_video = in_array( $first_item['type'], array( 'video', 'url' ), true );
            if ( $is_video && ! empty( $first_item['poster'] ) ) {
                $poster_id = (int) $first_item['poster'];
            }
            if ( $first_item['type'] === 'url' ) {
                $video_src = $first_item['src'] ?? '';
            } elseif ( $first_item['type'] === 'video' ) {
                $video_src = $image_id ? wp_get_attachment_url( $image_id ) : '';
            }
        }

        if ( ! $image_id && ! $is_video ) {
            $image_id = get_post_thumbnail_id( $product_id );
        }

        $display_id = $poster_id ?: $image_id;

        return array(
            'display_id' => $display_id,
            'is_video'   => $is_video,
            'image_id'   => $image_id,
            'video_src'  => $video_src,
        );
    }

    /**
     * Get aggregated card data for archive / listing loops.
     *
     * Combines card image, formatted price, and short description into one call,
     * avoiding repeated meta lookups and json_decode per card in templates.
     *
     * @param int     $product_id    Product post ID.
     * @param bool    $use_formatter Whether PufferGo_Unit_Formatter is available.
     * @return array {
     *     @type int    $display_id      Attachment ID to render.
     *     @type bool   $is_video        Whether the item is a video/url type.
     *     @type string $price_display   Formatted price string (empty if none).
     *     @type string $short_description Short description or empty string.
     * }
     */
    public static function get_card_data( $product_id, $use_formatter = false ) {
        $card = self::get_card_image( $product_id );

        $price_raw  = get_post_meta( $product_id, '_puffergo_price', true );
        $price_data = $price_raw ? json_decode( $price_raw, true ) : array();

        return array(
            'display_id'       => $card['display_id'],
            'is_video'         => $card['is_video'],
            'price_display'    => ( $use_formatter && $price_data ) ? PufferGo_Unit_Formatter::format( $price_data, 'currency' ) : '',
            'short_description' => get_post_meta( $product_id, '_puffergo_short_description', true ),
        );
    }

    public function sanitize_json_field( $value ) {
        if ( ! is_string( $value ) ) {
            return '';
        }
        $decoded = json_decode( $value, true );
        if ( json_last_error() !== JSON_ERROR_NONE ) {
            return '';
        }
        return wp_json_encode( $decoded );
    }

    public function auth_callback( $allowed, $meta_key, $post_id ) {
        return current_user_can( 'edit_post', $post_id );
    }

    public function rank_math_product_schema( $types ) {
        $types[ self::CPT_SLUG ] = 'Product';
        return $types;
    }

    /**
     * On first product publish, ensure product archive link is in the PufferGo header menu.
     */
    public function on_first_product_publish( $new_status, $old_status, $post ) {
        if ( $post->post_type !== self::CPT_SLUG ) {
            return;
        }
        if ( $new_status !== 'publish' || $old_status === 'publish' ) {
            return;
        }
        if ( get_option( 'puffergo_product_menu_injected' ) ) {
            return;
        }

        if ( ! function_exists( 'puffergo_ensure_primary_menu' ) ) {
            return;
        }

        $menu_id = puffergo_ensure_primary_menu();
        if ( $menu_id <= 0 ) {
            return;
        }

        $archive_url = get_post_type_archive_link( self::CPT_SLUG );
        if ( $archive_url ) {
            puffergo_add_custom_link_to_menu(
                $menu_id,
                __( 'Products', 'puffergo' ),
                $archive_url
            );
        }

        // Also inject into footer menu.
        $footer_menu_id = function_exists( 'puffergo_resolve_menu_id' )
            ? puffergo_resolve_menu_id( 'puffergo_footer', 'PufferGo Footer' )
            : 0;
        if ( $footer_menu_id > 0 && $archive_url ) {
            puffergo_add_custom_link_to_menu(
                $footer_menu_id,
                __( 'Products', 'puffergo' ),
                $archive_url
            );
        }

        update_option( 'puffergo_product_menu_injected', true );
    }

    /**
     * One-time migration: convert gallery format from [123,456] to [{type:"image",id:123},...].
     * Runs once on admin_init, then sets a flag so it never runs again.
     */
    public function migrate_gallery_format() {
        if ( get_option( 'puffergo_gallery_migrated_v2' ) ) {
            return;
        }
        $products = get_posts( array(
            'post_type'      => self::CPT_SLUG,
            'posts_per_page' => -1,
            'post_status'    => 'any',
        ) );
        foreach ( $products as $product ) {
            $raw = get_post_meta( $product->ID, '_puffergo_gallery', true );
            if ( empty( $raw ) ) {
                continue;
            }
            $items = json_decode( $raw, true );
            if ( ! is_array( $items ) ) {
                continue;
            }
            $needs_update = false;
            $converted = array();
            foreach ( $items as $item ) {
                if ( is_numeric( $item ) ) {
                    $converted[] = array( 'type' => 'image', 'id' => intval( $item ) );
                    $needs_update = true;
                } elseif ( is_array( $item ) && isset( $item['type'] ) ) {
                    $converted[] = $item;
                }
            }
            if ( $needs_update ) {
                update_post_meta( $product->ID, '_puffergo_gallery', wp_json_encode( $converted ) );
            }
        }
        update_option( 'puffergo_gallery_migrated_v2', true );
    }

}
