<?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 !', 'php-compatibility-checker-by-volade' ) . ' ' . $referral_link
        );

        $this->mission_definitions = array(
            'daily_checkin'    => array(
                'title'  => __( 'Connexion quotidienne', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Validez votre présence chaque jour pour maintenir votre série.', 'php-compatibility-checker-by-volade' ),
                'icon'   => '📅',
                'xp'     => 10,
                'type'   => 'daily_checkin',
                'repeat' => 'daily',
            ),
            'visit_volade'     => array(
                'title'  => __( 'Visiter Volade.com', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Découvrez le site officiel Volade.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Visionnez la vidéo Volade (au moins 15 secondes).', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Partagez votre lien de parrainage avec un ami.', 'php-compatibility-checker-by-volade' ),
                'icon'   => '👥',
                'xp'     => 50,
                'type'   => 'internal_link',
                'url'    => $referral_url,
                'repeat' => 'weekly',
            ),
            'copy_referral'    => array(
                'title'  => __( 'Copier son lien de parrainage', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Copiez votre lien et gardez-le sous la main.', 'php-compatibility-checker-by-volade' ),
                'icon'   => '🔗',
                'xp'     => 10,
                'type'   => 'copy_referral',
                'repeat' => 'daily',
            ),
            'share_twitter'    => array(
                'title'  => __( 'Partager sur X (Twitter)', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Publiez Volade sur X.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Partagez Volade sur Facebook.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Parlez de Volade sur LinkedIn.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Parcourez les plugins Volade disponibles.', 'php-compatibility-checker-by-volade' ),
                'icon'   => '🔍',
                'xp'     => 15,
                'type'   => 'internal_link',
                'url'    => $discover_url,
                'repeat' => 'weekly',
            ),
            'follow_newsletter' => array(
                'title'  => __( 'S\'inscrire à la newsletter', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Restez informé des nouveautés Volade.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Enrichissez votre site avec un autre outil Volade.', 'php-compatibility-checker-by-volade' ),
                'icon'   => '📦',
                'xp'     => 40,
                'type'   => 'auto_installs',
                'repeat' => 'once',
                'min'    => 2,
            ),
            'streak_bonus_7'   => array(
                'title'  => __( 'Série de 7 jours', 'php-compatibility-checker-by-volade' ),
                'desc'   => __( 'Bonus pour une série de 7 jours consécutifs.', 'php-compatibility-checker-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', 'php-compatibility-checker-by-volade' );
            case 'weekly':
                return __( 'Validé cette semaine', 'php-compatibility-checker-by-volade' );
            default:
                return __( 'Validé', 'php-compatibility-checker-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.', 'php-compatibility-checker-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.', 'php-compatibility-checker-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.', 'php-compatibility-checker-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.', 'php-compatibility-checker-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', 'php-compatibility-checker-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é.', 'php-compatibility-checker-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é.', 'php-compatibility-checker-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;
    }
}
