<?php
/**
 * Volade Promote — Missions, check-in quotidien, récompenses XP
 *
 * @package Volade\SDK
 * @license GPL-2.0-or-later
 */

trait Volade_Promote {

	/** @var array<string, array<string, mixed>>|null */
	private $mission_definitions = null;

	public function init_promote() {
		add_action( 'wp_ajax_volade_complete_mission', array( $this, 'ajax_complete_mission' ) );
		add_action( 'wp_ajax_volade_daily_checkin', array( $this, 'ajax_daily_checkin' ) );
	}

	/**
	 * @return array<string, array<string, mixed>>
	 */
	public function get_mission_definitions() {
		if ( null !== $this->mission_definitions ) {
			return $this->mission_definitions;
		}

		$discover_url  = admin_url( 'admin.php?page=volade-discover' );
		$referral_url  = admin_url( 'admin.php?page=volade-referrals' );
		$referral_link = '';

		$user = $this->get_current_user();
		if ( $user ) {
			$referral_link = $this->get_referral_link( $user['id'] );
		}

		$share_text = rawurlencode(
			__( 'Je teste les plugins Volade sur WordPress — rejoins-moi !', 'core-version-switcher-by-volade' ) . ' ' . $referral_link
		);

		$this->mission_definitions = array(
			'daily_checkin'         => array(
				'title'  => __( 'Connexion quotidienne', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Validez votre présence chaque jour pour maintenir votre série.', 'core-version-switcher-by-volade' ),
				'icon'   => '📅',
				'xp'     => 10,
				'type'   => 'daily_checkin',
				'repeat' => 'daily',
			),
			'visit_volade'          => array(
				'title'  => __( 'Visiter Volade.com', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Découvrez le site officiel Volade.', 'core-version-switcher-by-volade' ),
				'icon'   => '🌐',
				'xp'     => 15,
				'type'   => 'visit_url',
				'url'    => 'https://volade.com',
				'repeat' => 'weekly',
			),
			'watch_video'           => array(
				'title'  => __( 'Regarder la vidéo de présentation', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Visionnez la vidéo Volade (au moins 15 secondes).', 'core-version-switcher-by-volade' ),
				'icon'   => '🎬',
				'xp'     => 25,
				'type'   => 'watch_video',
				'url'    => 'https://www.youtube.com/watch?v=EngW7tLk6R8',
				'repeat' => 'weekly',
			),
			'invite_friend'         => array(
				'title'  => __( 'Inviter un ami', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Partagez votre lien de parrainage avec un ami.', 'core-version-switcher-by-volade' ),
				'icon'   => '👥',
				'xp'     => 50,
				'type'   => 'internal_link',
				'url'    => $referral_url,
				'repeat' => 'weekly',
			),
			'copy_referral'         => array(
				'title'  => __( 'Copier son lien de parrainage', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Copiez votre lien et gardez-le sous la main.', 'core-version-switcher-by-volade' ),
				'icon'   => '🔗',
				'xp'     => 10,
				'type'   => 'copy_referral',
				'repeat' => 'daily',
			),
			'share_twitter'         => array(
				'title'  => __( 'Partager sur X (Twitter)', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Publiez Volade sur X.', 'core-version-switcher-by-volade' ),
				'icon'   => '🐦',
				'xp'     => 20,
				'type'   => 'share_social',
				'url'    => 'https://twitter.com/intent/tweet?text=' . $share_text,
				'repeat' => 'daily',
			),
			'share_facebook'        => array(
				'title'  => __( 'Partager sur Facebook', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Partagez Volade sur Facebook.', 'core-version-switcher-by-volade' ),
				'icon'   => '📘',
				'xp'     => 20,
				'type'   => 'share_social',
				'url'    => 'https://www.facebook.com/sharer/sharer.php?u=' . rawurlencode( $referral_link ?: 'https://volade.com' ),
				'repeat' => 'daily',
			),
			'share_linkedin'        => array(
				'title'  => __( 'Partager sur LinkedIn', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Parlez de Volade sur LinkedIn.', 'core-version-switcher-by-volade' ),
				'icon'   => '💼',
				'xp'     => 20,
				'type'   => 'share_social',
				'url'    => 'https://www.linkedin.com/sharing/share-offsite/?url=' . rawurlencode( $referral_link ?: 'https://volade.com' ),
				'repeat' => 'daily',
			),
			'discover_plugins'      => array(
				'title'  => __( 'Explorer le catalogue', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Parcourez les plugins Volade disponibles.', 'core-version-switcher-by-volade' ),
				'icon'   => '🔍',
				'xp'     => 15,
				'type'   => 'internal_link',
				'url'    => $discover_url,
				'repeat' => 'weekly',
			),
			'follow_newsletter'     => array(
				'title'  => __( 'S\'inscrire à la newsletter', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Restez informé des nouveautés Volade.', 'core-version-switcher-by-volade' ),
				'icon'   => '📧',
				'xp'     => 20,
				'type'   => 'visit_url',
				'url'    => 'https://volade.com/#newsletter',
				'repeat' => 'once',
			),
			'install_second_plugin' => array(
				'title'  => __( 'Installer un 2ᵉ plugin Volade', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Enrichissez votre site avec un autre outil Volade.', 'core-version-switcher-by-volade' ),
				'icon'   => '📦',
				'xp'     => 40,
				'type'   => 'auto_installs',
				'repeat' => 'once',
				'min'    => 2,
			),
			'streak_bonus_7'        => array(
				'title'  => __( 'Série de 7 jours', 'core-version-switcher-by-volade' ),
				'desc'   => __( 'Bonus pour une série de 7 jours consécutifs.', 'core-version-switcher-by-volade' ),
				'icon'   => '🔥',
				'xp'     => 35,
				'type'   => 'auto_streak',
				'repeat' => 'once',
				'min'    => 7,
			),
		);

		return $this->mission_definitions;
	}

	public function get_mission_period_key( $repeat ) {
		switch ( $repeat ) {
			case 'daily':
				return wp_date( 'Y-m-d' );
			case 'weekly':
				return 'w-' . wp_date( 'o-W' );
			default:
				return 'once';
		}
	}

	public function is_mission_completed( $user_id, $mission_key, $repeat = 'once' ) {
		global $wpdb;

		$period = $this->get_mission_period_key( $repeat );

		return (bool) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT id FROM {$wpdb->prefix}volade_mission_completions
                 WHERE user_id = %d AND mission_key = %s AND period_key = %s LIMIT 1",
				$user_id,
				$mission_key,
				$period
			)
		);
	}

	/**
	 * @return string[]
	 */
	public function get_checkin_dates( $user_id, $days = 35 ) {
		global $wpdb;

		$since = wp_date( 'Y-m-d', strtotime( '-' . (int) $days . ' days' ) );

		$rows = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT period_key FROM {$wpdb->prefix}volade_mission_completions
                 WHERE user_id = %d AND mission_key = 'daily_checkin' AND period_key >= %s
                 ORDER BY period_key ASC",
				$user_id,
				$since
			)
		);

		return array_values( array_unique( array_map( 'strval', $rows ?: array() ) ) );
	}

	/**
	 * @return array<int, array<string, mixed>>
	 */
	public function get_missions_for_user( $user_id ) {
		$defs   = $this->get_mission_definitions();
		$user   = $this->get_user_data( $user_id );
		$streak = (int) ( $user['streak'] ?? 0 );

		global $wpdb;
		$plugin_count = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(DISTINCT plugin_slug) FROM {$wpdb->prefix}volade_events
                 WHERE user_id = %d AND event_type = 'plugin_active' AND plugin_slug != ''",
				$user_id
			)
		);

		$missions = array();
		foreach ( $defs as $key => $def ) {
			$repeat    = $def['repeat'] ?? 'once';
			$completed = $this->is_mission_completed( $user_id, $key, $repeat );
			$available = true;

			if ( 'auto_installs' === ( $def['type'] ?? '' ) ) {
				$available = $plugin_count >= (int) ( $def['min'] ?? 2 );
			} elseif ( 'auto_streak' === ( $def['type'] ?? '' ) ) {
				$available = $streak >= (int) ( $def['min'] ?? 7 );
			}

			$missions[] = array_merge(
				$def,
				array(
					'key'          => $key,
					'completed'    => $completed,
					'available'    => $available,
					'xp_label'     => '+' . (int) $def['xp'] . ' XP',
					'status_label' => $completed ? $this->get_mission_status_label( $repeat ) : '',
				)
			);
		}

		return $missions;
	}

	public function get_mission_status_label( $repeat = 'once' ) {
		switch ( $repeat ) {
			case 'daily':
				return __( 'Validé aujourd\'hui', 'core-version-switcher-by-volade' );
			case 'weekly':
				return __( 'Validé cette semaine', 'core-version-switcher-by-volade' );
			default:
				return __( 'Validé', 'core-version-switcher-by-volade' );
		}
	}

	/**
	 * @return array{completed:int,total:int}
	 */
	public function get_mission_progress( $user_id ) {
		$missions = $this->get_missions_for_user( $user_id );
		$done     = 0;
		foreach ( $missions as $mission ) {
			if ( ! empty( $mission['completed'] ) ) {
				++$done;
			}
		}
		return array(
			'completed' => $done,
			'total'     => count( $missions ),
		);
	}

	public function complete_mission( $user_id, $mission_key ) {
		$defs = $this->get_mission_definitions();
		$key  = sanitize_key( $mission_key );

		if ( ! isset( $defs[ $key ] ) ) {
			return new WP_Error( 'invalid_mission', __( 'Mission inconnue.', 'core-version-switcher-by-volade' ) );
		}

		$def    = $defs[ $key ];
		$repeat = $def['repeat'] ?? 'once';
		$type   = $def['type'] ?? 'manual';

		if ( $this->is_mission_completed( $user_id, $key, $repeat ) ) {
			return new WP_Error( 'already_done', __( 'Mission déjà validée pour cette période.', 'core-version-switcher-by-volade' ) );
		}

		if ( 'auto_installs' === $type || 'auto_streak' === $type ) {
			$missions = $this->get_missions_for_user( $user_id );
			$found    = null;
			foreach ( $missions as $m ) {
				if ( $m['key'] === $key ) {
					$found = $m;
					break;
				}
			}
			if ( ! $found || empty( $found['available'] ) ) {
				return new WP_Error( 'not_available', __( 'Conditions de la mission non remplies.', 'core-version-switcher-by-volade' ) );
			}
		}

		if ( 'daily_checkin' === $type ) {
			$this->record_activity( $user_id );
		}

		global $wpdb;
		$period = $this->get_mission_period_key( $repeat );

		$inserted = $wpdb->insert(
			"{$wpdb->prefix}volade_mission_completions",
			array(
				'user_id'      => $user_id,
				'mission_key'  => $key,
				'period_key'   => $period,
				'xp_awarded'   => (int) $def['xp'],
				'completed_at' => current_time( 'mysql' ),
			),
			array( '%d', '%s', '%s', '%d', '%s' )
		);

		if ( ! $inserted ) {
			return new WP_Error( 'db_error', __( 'Impossible d\'enregistrer la mission.', 'core-version-switcher-by-volade' ) );
		}

		$xp_result = $this->grant_xp(
			$user_id,
			(int) $def['xp'],
			'mission',
			array(
				'mission_key' => $key,
				'mission'     => $def['title'] ?? $key,
			)
		);

		$this->log_event(
			$user_id,
			'mission_completed',
			array(
				'mission_key' => $key,
				'title'       => $def['title'] ?? $key,
				'xp'          => (int) $def['xp'],
			)
		);

		$user = $this->get_user_data( $user_id );

		return array(
			'mission_key' => $key,
			'xp_earned'   => (int) $def['xp'],
			'total_xp'    => (int) ( $user['xp'] ?? 0 ),
			'streak'      => (int) ( $user['streak'] ?? 0 ),
			'level'       => (int) ( $user['level'] ?? 1 ),
			'level_up'    => ! empty( $xp_result['level_up'] ),
			'message'     => sprintf(
				/* translators: %d: XP points earned for the mission. */
				__( 'Mission validée ! +%d XP', 'core-version-switcher-by-volade' ),
				(int) $def['xp']
			),
		);
	}

	public function ajax_complete_mission() {
		check_ajax_referer( 'volade_nonce', 'nonce' );

		$user = $this->get_current_user();
		if ( ! $user ) {
			$this->send_promote_json_error( __( 'Non authentifié.', 'core-version-switcher-by-volade' ) );
		}

		$mission_key = sanitize_key( $_POST['mission_key'] ?? '' );
		$result      = $this->complete_mission( $user['id'], $mission_key );

		if ( is_wp_error( $result ) ) {
			$this->send_promote_json_error( $result->get_error_message() );
		}

		$this->send_promote_json_success( $result );
	}

	public function ajax_daily_checkin() {
		check_ajax_referer( 'volade_nonce', 'nonce' );

		$user = $this->get_current_user();
		if ( ! $user ) {
			$this->send_promote_json_error( __( 'Non authentifié.', 'core-version-switcher-by-volade' ) );
		}

		$result = $this->complete_mission( $user['id'], 'daily_checkin' );
		if ( is_wp_error( $result ) ) {
			$this->send_promote_json_error( $result->get_error_message() );
		}

		$this->send_promote_json_success( $result );
	}

	/**
	 * @param array<string, mixed> $result
	 */
	private function send_promote_json_success( array $result ) {
		$this->clean_ajax_output_buffer();

		$user     = $this->get_current_user();
		$progress = $user ? $this->get_mission_progress( $user['id'] ) : array(
			'completed' => 0,
			'total'     => 0,
		);
		$defs     = $this->get_mission_definitions();
		$key      = $result['mission_key'] ?? '';
		$repeat   = isset( $defs[ $key ] ) ? ( $defs[ $key ]['repeat'] ?? 'once' ) : 'once';

		wp_send_json_success(
			array(
				'message'         => $result['message'] ?? '',
				'xp_earned'       => (int) ( $result['xp_earned'] ?? 0 ),
				'total_xp'        => (int) ( $result['total_xp'] ?? 0 ),
				'streak'          => (int) ( $result['streak'] ?? 0 ),
				'level'           => (int) ( $result['level'] ?? 1 ),
				'level_up'        => ! empty( $result['level_up'] ),
				'mission_key'     => $key,
				'status_label'    => $this->get_mission_status_label( $repeat ),
				'completed_count' => (int) $progress['completed'],
				'total_missions'  => (int) $progress['total'],
			)
		);
	}

	private function send_promote_json_error( $message ) {
		$this->clean_ajax_output_buffer();
		wp_send_json_error( $message );
	}

	/**
	 * @return array<int, array{date:string,label:string,checked:bool,today:bool}>
	 */
	public function get_calendar_days( $user_id, $days = 28 ) {
		$checkins = array_flip( $this->get_checkin_dates( $user_id, $days ) );
		$today    = wp_date( 'Y-m-d' );
		$out      = array();

		for ( $i = $days - 1; $i >= 0; $i-- ) {
			$date  = wp_date( 'Y-m-d', strtotime( '-' . $i . ' days' ) );
			$out[] = array(
				'date'    => $date,
				'label'   => wp_date( 'j', strtotime( $date ) ),
				'weekday' => wp_date( 'D', strtotime( $date ) ),
				'checked' => isset( $checkins[ $date ] ),
				'today'   => $date === $today,
			);
		}

		return $out;
	}

	/**
	 * Aperçu missions pour visiteurs sans compte Volade.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public function get_missions_preview() {
		$missions = array();
		foreach ( $this->get_mission_definitions() as $key => $def ) {
			$missions[] = array_merge(
				$def,
				array(
					'key'           => $key,
					'completed'     => false,
					'available'     => true,
					'guest_preview' => true,
					'xp_label'      => '+' . (int) $def['xp'] . ' XP',
				)
			);
		}
		return $missions;
	}

	/**
	 * Calendrier vide pour aperçu invité.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public function get_calendar_preview( $days = 28 ) {
		$today = wp_date( 'Y-m-d' );
		$out   = array();

		for ( $i = $days - 1; $i >= 0; $i-- ) {
			$date  = wp_date( 'Y-m-d', strtotime( '-' . $i . ' days' ) );
			$out[] = array(
				'date'    => $date,
				'label'   => wp_date( 'j', strtotime( $date ) ),
				'weekday' => wp_date( 'D', strtotime( $date ) ),
				'checked' => false,
				'today'   => $date === $today,
			);
		}

		return $out;
	}
}
