<?php
/**
 * Plugin Name: Onedev Verified Customer Rating
 * Description: Product rating system based on verified customer phone number via shortcode [onedev_vcr_form].
 * Version: 1.3.6
 * Author: onedev.ovh
 * Author URI: https://onedev.ovh
 * Requires PHP: 8.1
 * Requires at least: 6.6
 * Tested up to: 7.1
 * WC requires at least: 8.2
 * WC tested up to: 11.1.0
 * Requires Plugins: woocommerce
 * Text Domain: onedev-verified-customer-rating-for-woocommerce
 * Domain Path: /languages/
 * License: GPL2
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Declare HPOS compatibility (Custom Order Tables).
 */
add_action( 'before_woocommerce_init', function () {
    if ( class_exists( '\\Automattic\\WooCommerce\\Utilities\\FeaturesUtil' ) ) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables',
            __FILE__,
            true
        );
    }
} );

/**
 * Load Composer autoload if present.
 */
$autoload = __DIR__ . '/vendor/autoload.php';
if ( file_exists( $autoload ) ) {
    require_once $autoload;
}

/**
 * Admin notice if libphonenumber is missing.
 */
add_action( 'admin_notices', function () {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    if ( ! class_exists( '\\libphonenumber\\PhoneNumberUtil' ) ) {
        echo '<div class="notice notice-warning"><p>'
            . esc_html__(
                'Onedev Verified Customer Rating: libphonenumber-for-php est manquante. Installez-la via Composer (vendor/autoload.php) pour activer la normalisation internationale des téléphones.',
                'onedev-verified-customer-rating-for-woocommerce'
            )
            . '</p></div>';
    }
} );

	add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_style(
        'onedev-verified-customer-rating',
        plugin_dir_url( __FILE__ ) . 'assets/css/customer-rating.css',
        array(),
        '1.0.0'
    );

    wp_enqueue_script(
        'onedev-verified-customer-rating',
        plugin_dir_url( __FILE__ ) . 'assets/js/customer-rating.js',
        array(),
        '1.0.0',
        true
    );
} );

function onedev_vcr_get_default_region() {
    if ( function_exists( 'WC' ) && WC()->customer ) {
        $c = WC()->customer->get_billing_country();
        if ( ! empty( $c ) ) {
            return $c;
        }
    }

    if ( function_exists( 'WC' ) ) {
        $base = wc_get_base_location();
        if ( ! empty( $base['country'] ) ) {
            return $base['country'];
        }
    }

    return 'TN';
}

/**
 * Normalize phone to E.164 via libphonenumber-for-php.
 * @return string|false
 */
function onedev_vcr_normalize_phone_e164( $raw_phone, $default_region = 'TN' ) {
    $raw_phone = sanitize_text_field( (string) $raw_phone );
    $raw_phone = trim( $raw_phone );

    if ( $raw_phone === '' ) {
        return false;
    }

    if ( ! class_exists( '\\libphonenumber\\PhoneNumberUtil' ) ) {
        return false;
    }

    $util = \libphonenumber\PhoneNumberUtil::getInstance();

    try {
        $proto = $util->parse( $raw_phone, strtoupper( (string) $default_region ) );

        if ( ! $util->isValidNumber( $proto ) ) {
            return false;
        }

        return $util->format( $proto, \libphonenumber\PhoneNumberFormat::E164 );
    } catch ( \Exception $e ) {
        return false;
    }
}

/**
 * Store E.164 phone on WooCommerce order at checkout (meta _billing_phone_e164).
 */
add_action( 'woocommerce_checkout_create_order', function( $order, $data ) {
    if ( ! is_a( $order, 'WC_Order' ) ) {
        return;
    }

    $billing_phone   = $order->get_billing_phone();
    $billing_country = $order->get_billing_country();

    if ( empty( $billing_country ) ) {
        $billing_country = onedev_vcr_get_default_region(); // fallback TN
    }

    // Normalisation avec région cohérente
    $e164 = onedev_vcr_normalize_phone_e164( $billing_phone, $billing_country );

    // Debug utile : stocker aussi le brut (optionnel)
    $order->update_meta_data( '_billing_phone_raw', sanitize_text_field( (string) $billing_phone ) );

    if ( $e164 ) {
        $order->update_meta_data( '_billing_phone_e164', $e164 );
    }
}, 20, 2 );


/**
 * Uniqueness: checks if a phone (E.164) already rated this product.
 */
function onedev_vcr_has_customer_already_rated_fr( $phone, $product_id ) {
    $default_region = onedev_vcr_get_default_region();
    $phone_e164     = onedev_vcr_normalize_phone_e164( $phone, $default_region );

    if ( ! $phone_e164 ) {
        return true;
    }

    $args = array(
        'post_id'    => (int) $product_id,
        'status'     => 'all',
        'meta_key'   => 'verified_phone',
        'meta_value' => $phone_e164,
        'count'      => true,
        'type'       => 'review',
    );

    $comments_count = get_comments( $args );
    return ( $comments_count > 0 );
}

/**
 * Verify existence of a "completed" order matching a phone (via _billing_phone_e164).
 */
function onedev_vcr_verify_customer_phone_number_fr( $phone ) {
    $default_region = onedev_vcr_get_default_region();
    $phone_e164     = onedev_vcr_normalize_phone_e164( $phone, $default_region );

    if ( ! $phone_e164 ) {
        return false;
    }

    $query_args = array(
        'status'     => array( 'completed' ),
        'limit'      => 1,
        'meta_query' => array(
            array(
                'key'     => '_billing_phone_e164',
                'value'   => $phone_e164,
                'compare' => '=',
            ),
        ),
    );

    $orders = wc_get_orders( $query_args );

    if ( ! empty( $orders ) ) {
        return $orders[0];
    }

    return false;
}

function onedev_vcr_approve_review( $comment_id, $product_id ) {
    wp_set_comment_status( $comment_id, 'approve' );

    if ( function_exists( 'wc_update_product_average_rating' ) ) {
        wc_update_product_average_rating( $product_id );
    }

    if ( function_exists( 'wc_delete_product_transients' ) ) {
        wc_delete_product_transients( $product_id );
    }

    update_post_meta(
        $product_id,
        '_wc_review_count',
        get_comments(
            array(
                'post_id' => $product_id,
                'count'   => true,
                'status'  => 'approve',
                'type'    => 'review',
            )
        )
    );
}

function onedev_vcr_shortcode_form_fr( $atts ) {
    $a = shortcode_atts(
        array(
            'product_id' => get_the_ID(),
        ),
        $atts
    );

    $product_id = (int) $a['product_id'];

    $message       = '';
    $message_class = '';
    $rating        = 0;
    $phone         = '';

    if ( isset( $_POST['submit_rating_fr'] ) ) {

        // FIX: Unsplash nonce before verify (Plugin Check warning).
        $nonce = isset( $_POST['customer_rating_nonce_fr'] ) ? sanitize_text_field( wp_unslash( $_POST['customer_rating_nonce_fr'] ) ): '';

        if ( ! wp_verify_nonce( $nonce, 'submit_customer_rating_action_fr' ) ) {
            $message       = esc_html__( 'Erreur de sécurité, veuillez réessayer.', 'onedev-verified-customer-rating-for-woocommerce' );
            $message_class = 'error';
        } else {
            $rating = isset( $_POST['customer_rating_fr'] ) ? (int) $_POST['customer_rating_fr'] : 0;

            // FIX: Unsplash then sanitize phone (Plugin Check warning).
            $phone = isset( $_POST['verification_phone_fr'] )
                ? sanitize_text_field( wp_unslash( $_POST['verification_phone_fr'] ) )
                : '';

            if ( ! class_exists( '\\libphonenumber\\PhoneNumberUtil' ) ) {
                $message       = esc_html__( 'Configuration manquante: le module de validation téléphone (libphonenumber) n\'est pas installé.', 'onedev-verified-customer-rating-for-woocommerce' );
                $message_class = 'error';
            } elseif ( $rating < 1 || $rating > 5 || empty( $phone ) ) {
                $message       = esc_html__( 'Veuillez saisir correctement la note et le numéro de téléphone.', 'onedev-verified-customer-rating-for-woocommerce' );
                $message_class = 'error';
            } else {
                if ( onedev_vcr_has_customer_already_rated_fr( $phone, $product_id ) ) {
                    $message       = esc_html__( 'Vous avez déjà soumis un avis pour ce produit avec ce numéro de téléphone.', 'onedev-verified-customer-rating-for-woocommerce' );
                    $message_class = 'error';
                } else {
                    $order_object = onedev_vcr_verify_customer_phone_number_fr( $phone );

                    if ( $order_object && is_a( $order_object, 'WC_Order' ) ) {
                        $first_name = $order_object->get_billing_first_name();
                        $last_name  = $order_object->get_billing_last_name();

                        $author_name = trim( $first_name . ' ' . $last_name );
                        $author_name = $author_name ? ( $author_name . ' (Client Vérifié)' ) : esc_html__( 'Client Vérifié', 'onedev-verified-customer-rating-for-woocommerce' );

                        $default_region = $order_object->get_billing_country();
                        if ( empty( $default_region ) ) {
                            $default_region = onedev_vcr_get_default_region();
                        }

                        $phone_e164 = onedev_vcr_normalize_phone_e164( $phone, $default_region );

                        if ( ! $phone_e164 ) {
                            $message       = esc_html__( 'Numéro de téléphone invalide. Exemple: +33 6 12 34 56 78 ou 06 12 34 56 78.', 'onedev-verified-customer-rating-for-woocommerce' );
                            $message_class = 'error';
                        } else {
                            $time = current_time( 'mysql' );

                            // FIX: Unsplash + sanitize IP (Plugin Check warning).
                            $ip = isset( $_SERVER['REMOTE_ADDR'] )
                                ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) )
                                : '';

/* translators: %d is rating 1..5 */
$comment_content_template = esc_html__( 'Avis client vérifié - Note : %d/5', 'onedev-verified-customer-rating-for-woocommerce' );

$comment_content = sprintf(
    $comment_content_template,
    (int) $rating
);

                            $review_data = array(
                                'comment_post_ID'      => $product_id,
                                'comment_author'       => esc_attr( $author_name ),
                                'comment_author_email' => 'client@verified.com',
                                'comment_content' => $comment_content,
                                'comment_author_url'   => '',
                                'comment_type'         => 'review',
                                'comment_parent'       => 0,
                                'user_id'              => 0,
                                'comment_author_IP'    => $ip,
                                'comment_date'         => $time,
                                'comment_approved'     => 0,
                            );

                            $comment_id = wp_insert_comment( $review_data );

                            if ( $comment_id ) {
                                update_comment_meta( $comment_id, 'rating', (int) $rating );
                                update_comment_meta( $comment_id, 'verified_phone', $phone_e164 );

                                onedev_vcr_approve_review( $comment_id, $product_id );

                                $message       = esc_html__( 'Merci! Votre évaluation a été reçue.', 'onedev-verified-customer-rating-for-woocommerce' );
                                $message_class = 'success';

                                $rating = 0;
                                $phone  = '';
                            } else {
                                $message       = esc_html__( 'Une erreur est survenue lors de l\'enregistrement des données.', 'onedev-verified-customer-rating-for-woocommerce' );
                                $message_class = 'error';
                            }
                        }
                    } else {
                        $message       = esc_html__( 'Désolé, ce numéro ne figure pas dans notre historique client (commande complétée).', 'onedev-verified-customer-rating-for-woocommerce' );
                        $message_class = 'error';
                    }
                }
            }
        }
    }

    ob_start();
    ?>

<div class="customer-rating-container-fr">
    <?php if ( $message ) : ?>
        <p id="rating-message-<?php echo esc_attr( $product_id ); ?>" class="rating-message-fr <?php echo esc_attr( $message_class ); ?>">
            <?php echo esc_html( $message ); ?>
        </p>
    <?php endif; ?>

    <form method="post" class="customer-rating-form-fr" action="">
        <p class="form-row form-row-wide">
            <label><?php echo esc_html__( 'Votre évaluation du produit :', 'onedev-verified-customer-rating-for-woocommerce' ); ?></label>

            <div class="rating-stars-wrapper" id="rating-stars-<?php echo esc_attr( $product_id ); ?>">
                <?php for ( $i = 5; $i >= 1; $i-- ) : ?>
                    <?php
/* translators: %d is the number of stars (1-5). */
$star_title_template = esc_html__( '%d étoiles', 'onedev-verified-customer-rating-for-woocommerce' );

$star_title = sprintf(
    $star_title_template,
    (int) $i
);
                    ?>
                    <input
                        type="radio"
                        id="star-<?php echo esc_attr( $product_id . '-' . $i ); ?>"
                        name="customer_rating_fr"
                        value="<?php echo esc_attr( $i ); ?>"
                        <?php checked( (int) $rating, (int) $i ); ?>
                        required
                    />
                    <label
                        class="star-label"
                        for="star-<?php echo esc_attr( $product_id . '-' . $i ); ?>"
                        title="<?php echo esc_attr( $star_title ); ?>"
                    >★</label>
                <?php endfor; ?>
            </div>
        </p>

        <p class="form-row form-row-wide">
            <label for="verification_phone_fr"><?php echo esc_html__( 'Téléphone (local ou +indicatif) :', 'onedev-verified-customer-rating-for-woocommerce' ); ?></label>
            <input
                type="tel"
                name="verification_phone_fr"
                id="verification_phone_fr"
                placeholder="<?php echo esc_attr__( 'Ex: +216 98 123 456, +33 6 12 34 56 78, 06 12 34 56 78', 'onedev-verified-customer-rating-for-woocommerce' ); ?>"
                required
                value="<?php echo esc_attr( $phone ); ?>"
            >
        </p>

        <?php wp_nonce_field( 'submit_customer_rating_action_fr', 'customer_rating_nonce_fr' ); ?>
        <input type="hidden" name="product_id_to_rate_fr" value="<?php echo esc_attr( $product_id ); ?>">

        <p class="form-row">
            <button type="submit" name="submit_rating_fr" value="1" class="button alt">
                <?php echo esc_html__( 'Évaluer', 'onedev-verified-customer-rating-for-woocommerce' ); ?>
            </button>
        </p>
    </form>
</div>


    <?php

    return ob_get_clean();
}

add_shortcode( 'onedev_vcr_form', 'onedev_vcr_shortcode_form_fr' );
