<?php
error_log("WPVG TEST EXECUTE : " . time());

/**
 * Plugin Name:       WP vCard Generator
 * Description:       
 * Requires at least: 6.3.0
 * Requires PHP:      7.4
 * Version:           1.1.7
 * Author:            Eric BARRIEU
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       wp_vcard_generator
 * Website:           https://projetsdigitaux.fr
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

$plugin_prefix = 'WPVCARDGENERATOR';

// Extract the version number
$plugin_data = get_file_data(__FILE__, ['Version' => 'Version']);

// Plugin Constants
define($plugin_prefix . '_DIR', plugin_basename(__DIR__));
define($plugin_prefix . '_BASE', plugin_basename(__FILE__));
define($plugin_prefix . '_PATH', plugin_dir_path(__FILE__));
define($plugin_prefix . '_VER', $plugin_data['Version']);
define($plugin_prefix . '_CACHE_KEY', 'wp_vcard_generator-cache-key-for-plugin');
define($plugin_prefix . '_REMOTE_URL', 'https://projetsdigitaux.fr/wp-content/plugins/hoster/inc/secure-download.php?file=json&download=2025&token=2a3664f3cb676f31121b2afe2dd99e6e');

require constant($plugin_prefix . '_PATH') . 'inc/update.php';

new WPVCARDGENERATOR_DPUpdateChecker(
	constant($plugin_prefix . '_BASE'),
	constant($plugin_prefix . '_VER'),
	constant($plugin_prefix . '_CACHE_KEY'),
	constant($plugin_prefix . '_REMOTE_URL'),
);

function wpvg_mail_from_name() {
    return 'Générateur de vCard Premium';
}

function wpvg_mail_from() {
    return 'info@chefprojetdigital.fr';
}

function wpvg_mail_content_type() {
    return 'text/html; charset=UTF-8';
}

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

define( 'WPVG_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'WPVG_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

/**
 * IMPORTANT :
 * On force l'expéditeur UNIQUEMENT pour CE plugin,
 * sans toucher aux autres sous-domaines.
 */

add_filter('wp_mail_from', 'wpvg_mail_from');
add_filter('wp_mail_from_name', 'wpvg_mail_from_name');
add_filter('wp_mail_content_type', 'wpvg_mail_content_type');

add_filter('phpmailer_init', function($phpmailer) {
    $phpmailer->Sender = wpvg_mail_from();
});

/**
 * Création des dossiers /vcards/ à l’activation du plugin
 */
function wpvg_create_vcards_dirs() {
    $root = trailingslashit( ABSPATH ) . 'vcards/';

    // /vcards/
    if ( ! is_dir( $root ) ) {
        wp_mkdir_p( $root );
    }

    // /vcards/pending/
    $pending = $root . 'pending/';
    if ( ! is_dir( $pending ) ) {
        wp_mkdir_p( $pending );
    }

    // /vcards/off/
    $off = $root . 'off/';
    if ( ! is_dir( $off ) ) {
        wp_mkdir_p( $off );
    }

    // /vcards/gdpr-youtube/
    $gdpr_youtube = $root . 'gdpr-youtube/';
    if ( ! is_dir( $gdpr_youtube ) ) {
        wp_mkdir_p( $gdpr_youtube );
    }

    // /vcards/gdpr-vimeo/
    $gdpr_vimeo = $root . 'gdpr-vimeo/';
    if ( ! is_dir( $gdpr_vimeo ) ) {
        wp_mkdir_p( $gdpr_vimeo );
    }

    // Fichiers de sécurité
    wpvg_write_htaccess_and_index( $root, false );        // /vcards/
    wpvg_write_htaccess_and_index( $pending, true );      // /vcards/pending/
    wpvg_write_htaccess_and_index( $off, true );          // /vcards/off/
    wpvg_write_htaccess_and_index( $gdpr_youtube, true ); // /vcards/gdpr-youtube/
    wpvg_write_htaccess_and_index( $gdpr_vimeo, true );   // /vcards/gdpr-vimeo/

    // 🔥 Correction automatique des permissions dès l’installation
    wpvg_fix_permissions( $root );
}

/**
 * Remplace le .htaccess de /vcards/off/ pour autoriser le téléchargement des ZIP
 */
function wpvg_ensure_off_htaccess() {

    $off_dir = trailingslashit(ABSPATH) . 'vcards/off/';

    if (!is_dir($off_dir)) {
        wp_mkdir_p($off_dir);
    }

    $htaccess_path = $off_dir . '.htaccess';

    // Compatible Apache 2.2 et 2.4
    $rules = "Options +Indexes\nAllow from all\nRequire all granted\n";

    // On écrase toujours, car wpvg_write_htaccess_and_index met "deny from all"
    file_put_contents($htaccess_path, $rules);
}
add_action('init', 'wpvg_ensure_off_htaccess');

/**
 * Écrit .htaccess + index.html dans un dossier donné
 *
 * @param string $dir      Chemin absolu du dossier
 * @param bool   $deny_all true = deny from all, false = juste protection PHP + no index
 */
function wpvg_write_htaccess_and_index( $dir, $deny_all = false ) {
    if ( ! is_dir( $dir ) ) {
        return;
    }

    // .htaccess
    $htaccess_path = $dir . '.htaccess';

    if ( $deny_all ) {
        $htaccess_content = "deny from all\n";
    } else {
        $htaccess_content = "Options -Indexes\n<Files *.php>\n    deny from all\n</Files>\n";
    }

    if ( ! file_exists( $htaccess_path ) ) {
        @file_put_contents( $htaccess_path, $htaccess_content );
    }

    // index.html
    $index_path    = $dir . 'index.html';
    $index_content = "<!-- Silence is golden -->";

    if ( ! file_exists( $index_path ) ) {
        @file_put_contents( $index_path, $index_content );
    }
}

/**
 * Corrige automatiquement les permissions des dossiers et fichiers vCard
 */
function wpvg_fix_permissions( $path ) {

    if ( is_dir( $path ) ) {
        // Dossier : 0755
        @chmod( $path, 0755 );

        // Parcours récursif
        $items = scandir( $path );
        foreach ( $items as $item ) {
            if ( $item === '.' || $item === '..' ) continue;
            wpvg_fix_permissions( $path . '/' . $item );
        }

    } else {
        // Fichier : 0644
        @chmod( $path, 0644 );
    }
}

/**
 * Activation d’une vCard via le lien email
 * URL : https://tonsite.com/?wpvg-activate=TOKEN
 */
function wpvg_maybe_handle_activation() {
    if ( empty( $_GET['wpvg-activate'] ) ) {
        return;
    }

    $token = sanitize_text_field( $_GET['wpvg-activate'] );

    $root        = trailingslashit( ABSPATH ) . 'vcards/';
    $pending_dir = $root . 'pending/' . $token . '/';

    if ( ! is_dir( $pending_dir ) ) {
        wpvg_die(
			"Lien d’activation invalide ou expiré.",
			"vCard > Activation invalide",
			array('response' => 400)
		);
    }

    $meta_path = $pending_dir . 'meta.json';
    if ( ! file_exists( $meta_path ) ) {
		wpvg_die(
			"Données de vCard introuvables.",
			"vCard > Données introuvables",
			array('response' => 404)
		);
    }

    $meta = json_decode( file_get_contents( $meta_path ), true );
    if ( ! is_array( $meta ) || empty( $meta['id'] ) ) {
		wpvg_die(
			"Données de vCard invalides.",
			"vCard > Données invalides",
			array('response' => 400)
		);
    }

    $vcard_id = sanitize_title( $meta['id'] );

    // Dossier final : /vcards/{id}/
    $target_dir = $root . $vcard_id . '/';

    // Si une ancienne version existe, on la supprime
    if ( is_dir( $target_dir ) && function_exists( 'wpvg_rrmdir' ) ) {
        wpvg_rrmdir( $target_dir );
    }

    // On déplace le dossier pending vers le dossier final
    if ( ! @rename( $pending_dir, $target_dir ) ) {
		wpvg_die(
			"Impossible d’activer la vCard (erreur de déplacement de dossier).",
			"vCard > Erreur d’activation",
			array('response' => 500)
		);
    }

	// 1. Création du dossier /private/
	$private = $target_dir . 'private/';
	if (!is_dir($private)) {
		wp_mkdir_p($private);
	}

	file_put_contents($private . '.htaccess', "Require all denied\n");

	$sensitive = [
		'data.json',
		"sauvegarde-vcard-$vcard_id.json",
		'meta.json',
		"$vcard_id.zip"
	];

	foreach ($sensitive as $file) {
		$srcFile = $target_dir . $file;
		$dstFile = $private . $file;

		if (file_exists($srcFile)) {
			rename($srcFile, $dstFile);
		}
	}

    // Mise à jour du meta.json
    $meta['status']          = 'active';
    $meta['last_validation'] = time();
    $meta['pending_token']   = null;
	$meta['reactivate_token'] = wp_generate_password(20, false);

    file_put_contents( $target_dir . 'meta.json', json_encode( $meta, JSON_PRETTY_PRINT ) );

    // ------------------------------------------------------------------
    // URLs utilisées dans l’email
    // ------------------------------------------------------------------
    $vcard_url = home_url( "/vcards/{$vcard_id}/index.html" );
    $zip_url   = home_url( "/vcards/{$vcard_id}/{$vcard_id}.zip" );

    // Sujet
    $subject = "Votre vCard est maintenant en ligne !";

	// ------------------------------------------------------------------
	// EMAIL D’ACTIVATION (2e email) — AVEC BOUTON DE DÉSACTIVATION + CYCLE DE VIE + BCC
	// ------------------------------------------------------------------

	$base = rtrim( get_site_url(), '/' );

	$vcard_url   = $base . "/vcards/{$vcard_id}/index.html";
	$zip_url     = $base . "/wp-content/plugins/wp-vcard-generator/download.php?id={$vcard_id}&file=zip&token={$meta['renew_token']}";

	$disable_url = $base . "/?wpvg-disable={$vcard_id}&token={$meta['renew_token']}";

	$headers = array(
		'Content-Type: text/html; charset=UTF-8',
		'Bcc: info@chefprojetdigital.fr'
	);

	$subject = "Votre vCard est maintenant en ligne !";

	$message  = "";
	$message .= "<p style='font-size:16px;margin-bottom:20px;'>Bonjour,</p>";
	$message .= "<p style='font-size:16px;margin-bottom:20px;'>Votre vCard est maintenant <strong>active</strong> et disponible en ligne.</p>";

	// Bouton Voir ma vCard (bleu)
	$message .= "<!--[if mso]>";
	$message .= "<v:roundrect xmlns:v='urn:schemas-microsoft-com:vml' href='{$vcard_url}' style='height:45px;v-text-anchor:middle;width:220px;' arcsize='10%' stroke='f' fillcolor='#0073e6'>";
	$message .= "<w:anchorlock/><center style='color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;'>Voir ma vCard</center>";
	$message .= "</v:roundrect>";
	$message .= "<![endif]-->";
	$message .= "<!--[if !mso]><!-- -->";
	$message .= "<a href='{$vcard_url}' style='display:inline-block;padding:12px 20px;background:#0073e6;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Voir ma vCard</a>";
	$message .= "<!--<![endif]-->";

	$message .= "<br><br>";

	// Bouton ZIP (gris)
	$message .= "<!--[if mso]>";
	$message .= "<v:roundrect xmlns:v='urn:schemas-microsoft-com:vml' href='{$zip_url}' style='height:45px;v-text-anchor:middle;width:260px;' arcsize='10%' stroke='f' fillcolor='#444444'>";
	$message .= "<w:anchorlock/><center style='color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;'>Télécharger le ZIP</center>";
	$message .= "</v:roundrect>";
	$message .= "<![endif]-->";
	$message .= "<!--[if !mso]><!-- -->";
	$message .= "<a href='{$zip_url}' style='display:inline-block;padding:12px 20px;background:#444444;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Télécharger le ZIP</a>";
	$message .= "<!--<![endif]-->";

	$message .= "<br><br>";
	
	// Cycle de vie
	$message .= "<h3 style='font-size:18px;margin-top:30px;'>📅 Cycle de vie de votre vCard</h3>";
	$message .= "<ul style='font-size:15px;line-height:1.6;color:#333;'>";
	$message .= "<li><strong>J+0</strong> → Activation</li>";
	$message .= "<li><strong>J+83</strong> → Email de relance automatique (7 jours avant expiration)</li>";
	$message .= "<li><strong>J+90</strong> → Désactivation automatique si non renouvelée</li>";
	$message .= "<li><strong>J+120</strong> → Suppression définitive (30 jours après désactivation)</li>";
	$message .= "</ul>";
	
	$message .= "<br>";
	
	// Bouton Désactiver (rouge)
	$message .= "<!--[if mso]>";
	$message .= "<v:roundrect xmlns:v='urn:schemas-microsoft-com:vml' href='{$disable_url}' style='height:45px;v-text-anchor:middle;width:280px;' arcsize='10%' stroke='f' fillcolor='#cc0000'>";
	$message .= "<w:anchorlock/><center style='color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;'>Désactiver ma vCard</center>";
	$message .= "</v:roundrect>";
	$message .= "<![endif]-->";
	$message .= "<!--[if !mso]><!-- -->";
	$message .= "<a href='{$disable_url}' style='display:inline-block;padding:12px 20px;background:#cc0000;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Désactiver ma vCard</a>";
	$message .= "<!--<![endif]-->";

	$message .= "<p style='font-size:14px;color:#555;margin-top:10px;'>Veillez à conserver cet email précieusement en cas de besoin pour désactiver votre vCard.<br>Attention : une désactivation de plus de 30 jours entraîne une suppression automatique.<br></p>";
	$message .= "<p style='font-size:14px;color:#555;margin-top:10px;'>Pour conserver une copie de vos informations et gérer votre vCard, il est conseillé de télécharger dès maintenant le dossier ZIP associé. Le fichier JSON contenu dans ce dossier vous sera nécessaire pour modifier votre vCard ultérieurement.</p>";

	$message .= "<p style='font-size:16px;margin-top:30px;'>Merci d'utiliser notre service !</p>";

// Envoi
wp_mail( $meta['email'], $subject, $message, $headers );

    // On mémorise la dernière vCard pour la page admin
    update_option( 'wpvg_last_vcard_id', $vcard_id );

    // Redirection finale
    $public_url = rtrim( get_site_url(), '/' ) . '/vcards/' . $vcard_id . '/index.html';
    wp_redirect( $public_url );
}
add_action( 'init', 'wpvg_maybe_handle_activation' );

/**
 * Ping de visite vCard
 * URL : https://tonsite.com/?wpvg-ping={vcard_id}
 * Appelé en JS depuis la vCard pour mettre à jour last_visit
 */
function wpvg_maybe_handle_ping() {
    if ( empty( $_GET['wpvg-ping'] ) ) {
        return;
    }

    $vcard_id = sanitize_title( $_GET['wpvg-ping'] );

    $root     = trailingslashit( ABSPATH ) . 'vcards/';
    $vcard_dir = $root . $vcard_id . '/';
    $meta_path = $vcard_dir . 'meta.json';

    if ( ! is_dir( $vcard_dir ) || ! file_exists( $meta_path ) ) {
        // On ne dit rien, on sort silencieusement
        exit;
    }

    $meta = json_decode( file_get_contents( $meta_path ), true );
    if ( ! is_array( $meta ) ) {
        exit;
    }

    $meta['last_visit'] = time();

    file_put_contents( $meta_path, json_encode( $meta, JSON_PRETTY_PRINT ) );

    // Réponse minimale pour le fetch JS
    wp_send_json( [ 'success' => true ] );
}
add_action( 'init', 'wpvg_maybe_handle_ping' );

/**
 * Cron autonome : expiration, relance, archivage, suppression
 */
function wpvg_auto_maintenance() {

    $root = trailingslashit(ABSPATH) . 'vcards/';
    $active_dir = $root;
    $off_dir    = $root . 'off/';
		
	// 0️⃣ — TRAITEMENT DES VCARD PENDING (suppression après 48h)
	$pending_dir = $root . 'pending/';
	$pending_items = scandir($pending_dir);

	foreach ($pending_items as $item) {
		if ($item === '.' || $item === '..') continue;

		$dir = $pending_dir . $item . '/';
		$meta_path = $dir . 'meta.json';

		if (!file_exists($meta_path)) continue;

		$meta = json_decode(file_get_contents($meta_path), true);
		if (!is_array($meta)) continue;

		$created_at = intval($meta['created_at'] ?? 0);
		if (!$created_at) continue;

		// Suppression après 48h
		if (time() - $created_at > 48 * 3600) {
			if (function_exists('wpvg_rrmdir')) {
				wpvg_rrmdir($dir);
			}
		}
	}

    // 1️⃣ — TRAITEMENT DES VCARD ACTIVES
    $items = scandir($active_dir);

    foreach ($items as $item) {
        if ($item === '.' || $item === '..' || $item === 'pending' || $item === 'off') {
            continue;
        }

        $vcard_dir = $active_dir . $item . '/';
        $meta_path = $vcard_dir . 'meta.json';

        if (!file_exists($meta_path)) continue;

        $meta = json_decode(file_get_contents($meta_path), true);
        if (!is_array($meta)) continue;

        // Vérification statut
        if (($meta['status'] ?? '') !== 'active') continue;

        $created       = intval($meta['created_at'] ?? 0);
        $validated     = intval($meta['last_validation'] ?? 0);
        $last_visit    = intval($meta['last_visit'] ?? 0);
        $validity_days = intval($meta['validity_days'] ?? 90);

        $now = time();
        $expire_at = $validated + ($validity_days * 86400);

        // 1.1 — Relance si expiration dans < 7 jours
        if ($expire_at - $now < 7 * 86400 && empty($meta['renew_notice_sent'])) {

            $renew_url = get_site_url() . '/?wpvg-renew=' . urlencode($meta['id']) . '&token=' . urlencode($meta['renew_token']);

            $subject = "Le cycle de votre vCard arrive à son terme.";
            $message = "<p>Bonjour,</p>
                        <p>Votre vCard <strong>{$meta['id']}</strong> expirera bientôt.</p>
                        <p><a href=\"$renew_url\" style=\"padding:12px 20px;background:#2271b1;color:#fff;text-decoration:none;border-radius:6px;\">Renouveler ma vCard</a></p>
                        <p>Sans renouvellement, elle sera désactivée automatiquement.</p>";

            add_filter('wp_mail_content_type', fn() => 'text/html; charset=UTF-8');

            $headers = array(
				'Content-Type: text/html; charset=UTF-8',
				'Bcc: info@chefprojetdigital.fr'
			);

			wp_mail($meta['email'], $subject, $message, $headers);

            $meta['renew_notice_sent'] = time();
            file_put_contents($meta_path, json_encode($meta, JSON_PRETTY_PRINT));
        }

        // 1.2 — Expiration → déplacement vers /off/
        if ($now > $expire_at) {

            $target = $off_dir . $meta['id'] . '/';

            if (is_dir($target) && function_exists('wpvg_rrmdir')) {
                wpvg_rrmdir($target);
            }

            @rename($vcard_dir, $target);

            $meta['status'] = 'off';
            $meta['off_since'] = time();

            file_put_contents($target . 'meta.json', json_encode($meta, JSON_PRETTY_PRINT));
        }
    }
	
	// 1.1 — Relance si expiration dans < 7 jours
	if ($expire_at - $now < 7 * 86400 && empty($meta['renew_notice_sent'])) {

		$renew_url = get_site_url() . '/?wpvg-renew=' . urlencode($meta['id']) . '&token=' . urlencode($meta['renew_token']);

		$subject = "Votre vCard arrive bientôt à expiration";
		$message = "<p>Bonjour,</p>
					<p>Votre vCard <strong>{$meta['id']}</strong> expirera bientôt.</p><br>
					<p><a href=\"$renew_url\" style=\"padding:12px 20px;background:#2271b1;color:#fff;text-decoration:none;border-radius:6px;\">Renouveler ma vCard</a></p><br>
					<p>Sans renouvellement, elle sera désactivée automatiquement.</p>";

		add_filter('wp_mail_content_type', fn() => 'text/html; charset=UTF-8');
		wp_mail($meta['email'], $subject, $message);

		$meta['renew_notice_sent'] = time();
		file_put_contents($meta_path, json_encode($meta, JSON_PRETTY_PRINT));
	}

    // 2️⃣ — TRAITEMENT DES VCARD OFF (suppression après 30 jours)
    $off_items = scandir($off_dir);

    foreach ($off_items as $item) {
        if ($item === '.' || $item === '..') continue;

        $dir = $off_dir . $item . '/';
        $meta_path = $dir . 'meta.json';

        if (!file_exists($meta_path)) continue;

        $meta = json_decode(file_get_contents($meta_path), true);
        if (!is_array($meta)) continue;

        $off_since = intval($meta['off_since'] ?? 0);
        if (!$off_since) continue;

        // Suppression après 30 jours
        if (time() - $off_since > 30 * 86400) {
            if (function_exists('wpvg_rrmdir')) {
                wpvg_rrmdir($dir);
            }
        }
    }
}
add_action('init', 'wpvg_auto_maintenance');

/**
 * Renouvellement d’une vCard via le lien email
 * URL : https://tonsite.com/?wpvg-renew={id}&token={renew_token}
 */
function wpvg_maybe_handle_renew() {

    if ( empty($_GET['wpvg-renew']) || empty($_GET['token']) ) {
        return;
    }

    $vcard_id = sanitize_title($_GET['wpvg-renew']);
    $token    = sanitize_text_field($_GET['token']);

    $root      = trailingslashit(ABSPATH) . 'vcards/';
    $vcard_dir = $root . $vcard_id . '/';
    $meta_path = $vcard_dir . 'meta.json';

    if ( ! is_dir($vcard_dir) || ! file_exists($meta_path) ) {
		wpvg_die(
			"Cette vCard n'existe plus ou a été supprimée.",
			"vCard > Introuvable",
			array('response' => 410)
		);
    }

    $meta = json_decode(file_get_contents($meta_path), true);
    if ( ! is_array($meta) ) {
		wpvg_die(
			"Données de vCard invalides.",
			"vCard > Données invalides",
			array('response' => 400)
		);
    }

    // Vérification du token
    if ( empty($meta['renew_token']) || $meta['renew_token'] !== $token ) {
		wpvg_die(
			"Lien de renouvellement invalide.",
			"vCard > Renouvellement invalide",
			array('response' => 400)
		);
    }

    // Mise à jour des données
    $meta['status']            = 'active';
    $meta['last_validation']   = time();
    $meta['renew_notice_sent'] = null; // On supprime la trace de relance

    // On peut aussi régénérer un nouveau token de renouvellement
    $meta['renew_token'] = wp_generate_password(20, false, false);

    file_put_contents($meta_path, json_encode($meta, JSON_PRETTY_PRINT));

    // URL publique finale
    $public_url = rtrim(get_site_url(), '/') . '/vcards/' . $vcard_id . '/index.html';

    // Message facultatif
    // echo "<p>Votre vCard a été renouvelée. Redirection...</p>";

    wp_redirect($public_url);
    exit;
}
add_action('init', 'wpvg_maybe_handle_renew');

/**
 * API upload (handler admin-post)
 */
require_once WPVG_PLUGIN_DIR . 'api-upload.php';
require_once WPVG_PLUGIN_DIR . 'includes/wpvg-admin-ajax.php';


class WP_vCard_Generator {

    public function __construct() {
        add_shortcode( 'vcard_generator', array( $this, 'render_shortcode' ) );
        add_action( 'admin_menu', array( $this, 'register_admin_page' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
    }

    /**
     * Page d’admin : QR de la dernière vCard
     */
    public function register_admin_page() {
        add_menu_page(
            'WP vCard Generator',
            'WP vCard',
            'manage_options',
            'wpvg-admin',
            array( $this, 'render_admin_page' ),
            'dashicons-id',
            80
        );
		    // Sous-menu : Gestion des vCards
		add_submenu_page(
			'wpvg-admin',
			'Gestion des vCards',
			'Gestion des vCards',
			'manage_options',
			'wpvg-vcards-manager',
			array( $this, 'render_vcards_manager_page' )
		);
    }
	
	public function enqueue_admin_assets( $hook ) {

		if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'wpvg-vcards-manager' ) {
			return;
		}

		// 1. QRCode d'abord
		wp_enqueue_script(
			'wpvg-qrcode',
			plugin_dir_url( __FILE__ ) . 'assets/js/qrcode.min.js',
			array(),
			time(), // change la version pour casser le cache
			true
		);

		// 2. Puis ton JS admin, qui dépend de qrcode
		wp_enqueue_script(
			'wpvg-admin-vcards',
			plugin_dir_url( __FILE__ ) . 'assets/js/wpvg-admin-vcards.js',
			array( 'jquery', 'wpvg-qrcode' ),
			'1.0.1', // idem
			true
		);

		// 3. Localisation
		wp_localize_script(
			'wpvg-admin-vcards',
			'WPVG_ADMIN',
			array(
				'ajax_url'     => admin_url( 'admin-ajax.php' ),
				'nonce'        => wp_create_nonce( 'wpvg_admin_nonce' ),
				'download_url' => plugins_url( 'download.php', __FILE__ ),
			)
		);
	}


	public function render_vcards_manager_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		?>
		<div class="wrap">
			<h1>Gestion des vCards</h1>

			<p>Recherche globale (prénom, nom, vcardId) :</p>
			<input type="text" id="wpvg-search" class="regular-text" placeholder="Rechercher une vCard..." />

			<hr />

			<h2>vCards actives</h2>
			<div id="wpvg-active-wrapper">
				<p>Chargement des vCards actives...</p>
			</div>

			<hr />

			<h2>vCards en attente (pending)</h2>
			<div id="wpvg-pending-wrapper">
				<p>Chargement des vCards en attente...</p>
			</div>

			<hr />

			<h2>vCards désactivées (off)</h2>
			<div id="wpvg-off-wrapper">
				<p>Chargement des vCards désactivées...</p>
			</div>

			<!-- Modale de confirmation (style WP simple) -->
			<div id="wpvg-modal-overlay" style="display:none;">
				<div id="wpvg-modal" class="wpvg-modal">
					<h2 id="wpvg-modal-title"></h2>
					<p id="wpvg-modal-message"></p>
					<p class="submit">
						<button type="button" class="button button-secondary" id="wpvg-modal-cancel">Annuler</button>
						<button type="button" class="button button-primary" id="wpvg-modal-confirm">Confirmer</button>
					</p>
				</div>
			</div>
			<!-- Modale QR -->
			<div id="wpvg-qr-overlay" style="display:none;">
				<div id="wpvg-qr-modal" class="wpvg-modal">
					<h2>QR Code</h2>
					<div id="wpvg-qr-container" style="text-align:center; padding:20px;"></div>
					<p class="submit">
						<button type="button" class="button button-secondary" id="wpvg-qr-close">Fermer</button>
					</p>
				</div>
			</div>
			<hr />
			
			<h2>Nettoyage des miniatures GDPR</h2>
			<p>Supprime toutes les miniatures temporaires YouTube/Vimeo.</p>

			<button id="wpvg-clean-gdpr" class="button button-primary">
				Supprimer les miniatures GDPR
			</button>

			<div id="wpvg-clean-result" style="margin-top:10px;"></div>

		</div>
		<?php
	}

    public function render_admin_page() {

        $vcard_id = get_option( 'wpvg_last_vcard_id' );

        echo '<div class="wrap">';
        echo '<h1>WP vCard Generator</h1>';

        if ( ! $vcard_id ) {
            echo '<p>Aucune vCard générée pour le moment.</p>';
            echo '</div>';
            return;
        }

		$public_url = rtrim( get_site_url(), '/' ) . '/vcards/' . $vcard_id . '/index.html';

        if ( function_exists( 'wpvg_generate_qr_base64' ) ) {
            $qr_base64 = wpvg_generate_qr_base64( $public_url );
        } else {
            $qr_base64 = '';
        }

        echo '
            <div style="background:#fff;border:1px solid #ddd;padding:20px;border-radius:12px;max-width:380px;margin-top:20px;">
                <h2 style="margin-top:0;">QR Code de la dernière vCard</h2>

                <div style="text-align:center;">
                    ' . ( $qr_base64 ? '<img src="' . esc_attr( $qr_base64 ) . '" style="width:180px;height:180px;border-radius:8px;border:1px solid #eee;background:#fff;padding:10px;">' : '<p>Impossible de générer le QR code.</p>' ) . '
                </div>

                <p style="font-size:12px;word-break:break-all;margin-top:10px;">
                    ' . esc_html( $public_url ) . '
                </p>

                <button class="button copy-vcard-link" data-link="' . esc_attr( $public_url ) . '" style="width:100%;margin-top:10px;">
                    Copier le lien
                </button>

                ' . ( $qr_base64 ? '<a download="qrcode-' . esc_attr( $vcard_id ) . '.png" href="' . esc_attr( $qr_base64 ) . '" class="button" style="width:100%;margin-top:10px;text-align:center;">
                    Télécharger le QR
                </a>' : '' ) . '
            </div>

            <script>
                document.addEventListener("click", function(e){
                    if(e.target.classList.contains("copy-vcard-link")){
                        navigator.clipboard.writeText(e.target.dataset.link);
                        e.target.textContent = "Copié !";
                        setTimeout(()=>{ e.target.textContent = "Copier le lien"; }, 1500);
                    }
                });
            </script>
        ';

        echo '</div>';
    }

	/**
	 * Shortcode [vcard_generator]
	 */
	public function render_shortcode( $atts = array(), $content = null ) {

		// Version dynamique pour bust de cache
		$version = time();

		// 1. Vue.js
		wp_enqueue_script(
			'vuejs',
			WPVG_PLUGIN_URL . 'assets/js/vue.global.prod.js',
			array(),
			$version,
			true
		);

		// 4. JSZip
		wp_enqueue_script(
			'jszip',
			WPVG_PLUGIN_URL . 'assets/js/jszip.min.js',
			array(),
			$version,
			true
		);

		// 5. FileSaver
		wp_enqueue_script(
			'filesaver',
			WPVG_PLUGIN_URL . 'assets/js/FileSaver.min.js',
			array( 'jszip' ),
			$version,
			true
		);

		// 6. Sortable
		wp_enqueue_script(
			'sortable',
			WPVG_PLUGIN_URL . 'assets/js/Sortable.min.js',
			array(),
			$version,
			true
		);

		// 9. Icônes
		wp_enqueue_script(
			'wpvg-icons',
			WPVG_PLUGIN_URL . 'assets/js/icons.js',
			array(),
			$version,
			true
		);

		wp_enqueue_script(
			'wpvg-script',
			WPVG_PLUGIN_URL . 'assets/js/app.js',
			array('vuejs'),
			time(),
			true
		);

		wp_localize_script(
			'wpvg-script',
			'wpvg_ajax',
			[
				'ajax_url' => admin_url('admin-ajax.php'),
				'nonce'    => wp_create_nonce('wpvg_admin_nonce')
			]
		);

		// 2. QRCode
		wp_enqueue_script(
			'qrcode-js',
			WPVG_PLUGIN_URL . 'assets/js/qrcode.min.js',
			array(),
			$version,
			true
		);

		// 3. PDF.js
		wp_enqueue_script(
			'pdf-js',
			WPVG_PLUGIN_URL . 'assets/js/pdf.min.js',
			array(),
			$version,
			true
		);

		// 7. Quill CSS + JS
		wp_enqueue_style(
			'quill-css',
			WPVG_PLUGIN_URL . 'assets/css/quill.snow.css',
			array(),
			$version
		);

		wp_enqueue_script(
			'quill-js',
			WPVG_PLUGIN_URL . 'assets/js/quill.min.js',
			array(),
			$version,
			true
		);

		// 8. Styles du plugin
		wp_enqueue_style(
			'wpvg-style',
			WPVG_PLUGIN_URL . 'assets/css/style.css',
			array(),
			$version
		);

		// 9.5 Pickr (Color Picker)
		wp_enqueue_style(
			'wpvg-pickr',
			WPVG_PLUGIN_URL . 'assets/css/nano.min.css',
			array(),
			$version
		);

		wp_enqueue_script(
			'wpvg-pickr',
			WPVG_PLUGIN_URL . 'assets/js/pickr.min.js',
			array(),
			$version,
			true
		);

		// 10.5 Composant vidéo (YouTube + Vimeo)
		wp_enqueue_script(
			'wpvg-gdpr-video',
			WPVG_PLUGIN_URL . 'assets/js/gdpr-video.js',
			array( 'wpvg-script' ),
			$version,
			true
		);

		wp_localize_script(
			'wpvg-script',
			'wpvg_vars',
			[
				'plugin_url' => WPVG_PLUGIN_URL
			]
		);

		wp_localize_script(
			'wpvg-script',
			'wpvg_data',
			array(
				'plugin_url' => WPVG_PLUGIN_URL,
				'site_url'   => site_url(),
			)
		);

		// 11. Template
		ob_start();
		$template_path = WPVG_PLUGIN_DIR . 'templates/generator.php';

		if ( file_exists( $template_path ) ) {
			include $template_path;
		} else {
			echo '<div style="color:red;padding:20px;border:1px solid red;">Erreur : template introuvable.</div>';
		}

		return ob_get_clean();
	}
}

new WP_vCard_Generator();

// ------------------------------------------------------------------
// HANDLER : Désactivation manuelle via email
// ------------------------------------------------------------------
function wpvg_maybe_handle_disable() {

    if (empty($_GET['wpvg-disable']) || empty($_GET['token'])) {
        return;
    }

    $id    = sanitize_title($_GET['wpvg-disable']);
    $token = sanitize_text_field($_GET['token']);

    $root = trailingslashit(ABSPATH) . 'vcards/';
    $dir  = $root . $id . '/';
    $meta_path = $dir . 'meta.json';

    if (!is_dir($dir) || !file_exists($meta_path)) {
		wpvg_die(
			"Cette vCard n'existe plus.",
			"vCard > Introuvable",
			array('response' => 410)
		);
    }

    $meta = json_decode(file_get_contents($meta_path), true);

    // ON GARDE renew_token POUR QUE LE BOUTON DU 2e EMAIL FONCTIONNE
    if (!is_array($meta) || $meta['renew_token'] !== $token) {
		wpvg_die(
			"Lien invalide ou expiré.",
			"vCard > Lien invalide",
			array('response' => 400)
		);
    }

    // Déplacement dans /off/
    $off_dir = $root . 'off/' . $id . '/';

    if (is_dir($off_dir)) {
        wpvg_rrmdir($off_dir);
    }

    @rename($dir, $off_dir);

    // Mise à jour meta
    $meta['status']    = 'off';
    $meta['off_since'] = time();

    file_put_contents($off_dir . 'meta.json', json_encode($meta, JSON_PRETTY_PRINT));

    // Email confirmation PREMIUM mais texte adouci (anti‑spam)
    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        'Bcc: info@chefprojetdigital.fr'
    );

    $subject = "Votre vCard a été mise à jour";

    $reactivate_url = home_url( "/?wpvg-reactivate={$id}&token=" . urlencode($meta['reactivate_token']) );
    $zip_url = home_url( "/wp-content/plugins/wp-vcard-generator/download.php?id={$id}&file=zip&token=" . urlencode($meta['renew_token']) );

    $message  = "";
    $message .= "<p style='font-size:16px;font-family:Arial,sans-serif;margin-bottom:20px;'>Bonjour,</p>";
    $message .= "<p style='font-size:16px;font-family:Arial,sans-serif;margin-bottom:20px;'>
	Votre vCard <strong>{$id}</strong> n’est plus affichée pour le moment.
	</p>";
    $message .= "<p style='font-size:16px;font-family:Arial,sans-serif;margin-bottom:20px;'>
	Vous pouvez la remettre en ligne ou télécharger une copie.
	</p>";

    // Bouton Réactiver
    $message .= "<p style='margin:25px 0;'>
	<a href='{$reactivate_url}' 
	   style='display:inline-block;padding:12px 20px;background:#0073e6;
			  color:#ffffff !important;text-decoration:none;font-size:16px;
			  font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>
	Réactiver ma vCard
	</a>
	</p>";

    // Bouton ZIP
    $message .= "<p style='margin:15px 0;'>
	<a href='{$zip_url}' 
	   style='display:inline-block;padding:12px 20px;background:#444444;
			  color:#ffffff !important;text-decoration:none;font-size:16px;
			  font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>
	Télécharger le ZIP
	</a>
	</p>";

    $message .= "<p style='font-size:14px;font-family:Arial,sans-serif;color:#555;margin-top:25px;'>
	Votre vCard restera en pause pendant 30 jours. Vous pouvez la réactiver à tout moment.
	</p>";

	// Bouton Supprimer définitivement
	$delete_url = home_url( "/?wpvg-delete={$id}&token=" . urlencode($meta['renew_token']) );

	$message .= "<p style='margin:15px 0;'>
	<a href='{$delete_url}' 
	   style='display:inline-block;padding:12px 20px;background:#cc0000;
			  color:#ffffff !important;text-decoration:none;font-size:16px;
			  font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>
	Retirer mes informations
	</a>
	</p>";

	$message .= "<p style='font-size:14px;font-family:Arial,sans-serif;color:#555;margin-top:10px;'>
	Si vous souhaitez retirer immédiatement toutes vos informations de notre système, vous pouvez utiliser le bouton ci‑dessus.
	</p>";


    $message .= "<p style='font-size:16px;font-family:Arial,sans-serif;margin-top:30px;'>
	Merci d'utiliser notre service.
	</p>";

    wp_mail($meta['email'], $subject, $message, $headers);

	wpvg_die(
		"<h2>Votre vCard a été mise en pause.</h2><p>Vous pouvez la réactiver à tout moment via l'email reçu.</p>",
		"vCard > Mise en pause",
		array('response' => 200)
	);
}
add_action('init', 'wpvg_maybe_handle_disable');

// ------------------------------------------------------------------
// HANDLER : Réactivation manuelle via email
// ------------------------------------------------------------------
function wpvg_maybe_handle_reactivation() {
    if ( empty($_GET['wpvg-reactivate']) ) return;

    $id    = sanitize_title($_GET['wpvg-reactivate']);
    $token = sanitize_text_field($_GET['token']);

    $root      = ABSPATH . 'vcards/';
    $off_dir   = $root . 'off/' . $id . '/';
    $active_dir= $root . $id . '/';

    if (!is_dir($off_dir)) 
		wpvg_die(
			"Lien invalide.",
			"vCard > Lien invalide",
			array('response' => 400)
		);
    $meta = json_decode(file_get_contents($off_dir . 'meta.json'), true);
    if (!is_array($meta) || $meta['reactivate_token'] !== $token) 
		wpvg_die(
			"Token invalide.",
			"vCard > Token invalide",
			array('response' => 400)
		);

    // Déplacement
    rename($off_dir, $active_dir);

    // Mise à jour meta
    $meta['status']          = 'active';
    $meta['last_validation'] = time();
    file_put_contents($active_dir . 'meta.json', json_encode($meta, JSON_PRETTY_PRINT));

    // URL publique
    $public_url = home_url("/vcards/{$id}/index.html");

    // EMAIL DE RÉACTIVATION
    $reactivate_subject = "Votre vCard est disponible en ligne";

    $reactivate_headers = array(
        'Content-Type: text/html; charset=UTF-8',
        'Bcc: info@chefprojetdigital.fr'
    );

    $reactivate_message  = "";
    $reactivate_message .= "<p style='font-size:16px;margin-bottom:20px;'>Bonjour,</p>";
    $reactivate_message .= "<p style='font-size:16px;margin-bottom:20px;'>Votre vCard a été <strong>réactivée</strong> avec succès.</p>";
    $reactivate_message .= "<p style='font-size:16px;margin-bottom:20px;'>Votre vCard est maintenant accessible.</p>";

    // Bouton Voir ma vCard
    $reactivate_message .= "<a href='{$public_url}' style='display:inline-block;padding:12px 20px;background:#0073e6;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Voir ma vCard</a>";

    $reactivate_message .= "<br><br>";

    // Bouton Télécharger ZIP
    $zip_url = home_url( "/wp-content/plugins/wp-vcard-generator/download.php?id={$id}&file=zip&token=" . urlencode($meta['renew_token']) );
    $reactivate_message .= "<a href='{$zip_url}' style='display:inline-block;padding:12px 20px;background:#444444;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Télécharger le ZIP</a>";

    $reactivate_message .= "<br><br>";

    // Bouton Désactiver (UTILISE renew_token, comme ton 2e email)
    $disable_url = home_url( "/?wpvg-disable={$id}&token=" . urlencode($meta['renew_token']) );
    $reactivate_message .= "<a href='{$disable_url}' style='display:inline-block;padding:12px 20px;background:#cc0000;color:#ffffff !important;text-decoration:none;font-size:16px;font-weight:bold;border-radius:6px;font-family:Arial,sans-serif;'>Mettre hors ligne</a>";

    $reactivate_message .= "<p style='font-size:14px;color:#555;margin-top:10px;'>Vous pouvez mettre votre vCard hors ligne à tout moment.</p>";

    wp_mail( $meta['email'], $reactivate_subject, $reactivate_message, $reactivate_headers );

    wp_redirect($public_url);
    exit;
}
add_action('init', 'wpvg_maybe_handle_reactivation');

// ------------------------------------------------------------------
// HANDLER : Suppression définitive via email
// ------------------------------------------------------------------
function wpvg_maybe_handle_delete() {

    if (empty($_GET['wpvg-delete']) || empty($_GET['token'])) {
        return;
    }

    $id    = sanitize_title($_GET['wpvg-delete']);
    $token = sanitize_text_field($_GET['token']);

    $root = trailingslashit(ABSPATH) . 'vcards/';
    $off_dir = $root . 'off/' . $id . '/';
    $meta_path = $off_dir . 'meta.json';

    if (!is_dir($off_dir) || !file_exists($meta_path)) {
		wpvg_die(
			"Cette vCard n'existe plus.",
			"vCard > Introuvable",
			array('response' => 410)
		);
    }

    $meta = json_decode(file_get_contents($meta_path), true);

    // Vérification : même token que la désactivation
    if (!is_array($meta) || $meta['renew_token'] !== $token) {
		wpvg_die(
			"Lien invalide ou expiré.",
			"vCard > Lien invalide",
			array('response' => 400)
		);
    }

    // Suppression définitive
    wpvg_rrmdir($off_dir);

	wpvg_die(
		"<h2>Votre vCard a été supprimée définitivement.</h2><p>Toutes les données associées ont été retirées de nos serveurs.</p>",
		"vCard > Suppression définitive",
		array('response' => 200)
	);
}
add_action('init', 'wpvg_maybe_handle_delete');

// 👉 ICI : favicon multi-format
add_action('wp_head', function() {

    // Apple iOS / iPadOS
    echo '<link rel="apple-touch-icon" sizes="180x180" href="' . esc_url( home_url('/vcard-apple-touch-icon.png') ) . '">';

    // Favicon PNG standard
    echo '<link rel="icon" type="image/png" sizes="32x32" href="' . esc_url( home_url('/vcard-favicon-32x32.png') ) . '">';
    echo '<link rel="icon" type="image/png" sizes="16x16" href="' . esc_url( home_url('/vcard-favicon-16x16.png') ) . '">';

    // Favicon ICO (compatibilité Windows / vieux navigateurs)
    echo '<link rel="icon" type="image/x-icon" href="' . esc_url( home_url('/vcard-favicon.ico') ) . '">';

    // Android Chrome (PWA)
    echo '<link rel="icon" type="image/png" sizes="192x192" href="' . esc_url( home_url('/vcard-android-chrome-192x192.png') ) . '">';
    echo '<link rel="icon" type="image/png" sizes="512x512" href="' . esc_url( home_url('/vcard-android-chrome-512x512.png') ) . '">';

    // Manifest PWA
    echo '<link rel="manifest" href="' . esc_url( home_url('/vcard-site.webmanifest') ) . '">';

});
function wpvg_die($message, $title = '', $response = 200) {

    // Injection HTML du pack favicon (fiable à 100%)
    $favicon_html = '
        <link rel="icon" type="image/png" sizes="32x32" href="' . esc_url( home_url('/vcard-favicon-32x32.png') ) . '">
        <link rel="icon" type="image/png" sizes="16x16" href="' . esc_url( home_url('/vcard-favicon-16x16.png') ) . '">
        <link rel="icon" type="image/x-icon" href="' . esc_url( home_url('/vcard-favicon.ico') ) . '">
        <link rel="apple-touch-icon" sizes="180x180" href="' . esc_url( home_url('/vcard-apple-touch-icon.png') ) . '">
        <link rel="manifest" href="' . esc_url( home_url('/vcard-site.webmanifest') ) . '">
    ';

    wp_die(
        $favicon_html . $message,
        $title,
        array(
            'response' => $response
        )
    );
}
