<?php
/**
 * includes/referral-system.php
 *
 * ============================================================================
 * SISTEMA DE CONVITES (REFERRALS) — 1.5.131
 * ============================================================================
 *
 * REGRA DE NEGÓCIO:
 *   A comissão ao convidador (referrer) só é creditada quando o convidado
 *   (buyer) cumprir DUAS condições cumulativas:
 *
 *     1. Tem o 1º depósito APROVADO pelo admin
 *     2. Compra um plano VIP (qualquer)
 *
 *   Trigger duplo evita fraude: alguém criar conta + depositar e nunca
 *   activar plano não dispara comissão. Garante que o convite resulta
 *   num utilizador que realmente entrou no produto.
 *
 * FLUXO COMPLETO:
 *
 *   PASSO 1 — REGISTO
 *     Utilizador A regista-se com "Convidado por: tel_B".
 *     `referred_by = tel_B` na tabela rmbz_wallets.
 *     Linha em rmbz_referral_log com status=pending.
 *
 *   PASSO 2 — 1º DEPÓSITO APROVADO
 *     Admin aprova depósito de A → hook
 *     `rmbz_first_deposit_approved($buyer_tel, $amount)` é disparado.
 *     Marca-se `first_deposit_approved_at` no log.
 *     Se `plan_purchased_at` JÁ estava marcado (compra antes do depósito
 *     ser aprovado, ex: cupão), conclui-se imediatamente. Senão fica
 *     a aguardar.
 *
 *   PASSO 3 — COMPRA DE PLANO VIP
 *     A compra um plano VIP → hook
 *     `rmbz_vip_plan_purchased($buyer_tel, $plan_id)` é disparado.
 *     Marca-se `plan_purchased_at` no log.
 *     Se `first_deposit_approved_at` JÁ estava marcado, conclui-se.
 *
 *   CONCLUSÃO (ambas as condições cumpridas):
 *     - Calcula recompensa segundo o tipo (MT ou dias VIP)
 *     - Credita carteira do referrer (MT) OU adiciona dias à subscrição
 *     - Marca status=completed, completed_at=NOW()
 *     - Cria notificação para o referrer
 *
 * RECOMPENSAS (admin escolhe em Settings → 1MZ → Convites):
 *   - 'mt'   : commission_amount = (deposit_amount × rmbz_referral_rate / 100)
 *   - 'days' : commission_days = rmbz_referral_days (fixo)
 *
 * ANTI-FRAUDE:
 *   - Auto-referral: bloqueado (referrer === buyer)
 *   - Blacklist: número na lista negra não recebe comissão
 *   - Duplicados: PRIMARY KEY no log + check buyer_telemovel já tem entry
 *   - Status='pending' single-row: cria-se uma vez no registo, atualiza-se
 *     em vez de criar nova
 */

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


/**
 * Helper: lê tabela do log.
 */
function rmbz_referral_log_table() {
    global $wpdb;
    return $wpdb->prefix . 'rmbz_referral_log';
}


/**
 * Cria entrada pending no log no momento do registo.
 * Chamada do form-handler quando referred_by é gravado.
 *
 * @param string $buyer_tel  Quem se registou
 * @param string $referrer_tel  Quem convidou
 * @return bool true se criou, false se inválido ou duplicado
 */
function rmbz_referral_create_pending( $buyer_tel, $referrer_tel ) {
    if ( empty($buyer_tel) || empty($referrer_tel) ) return false;
    if ( $buyer_tel === $referrer_tel ) return false; // self-ref

    // Blacklist
    $blacklist = (array) get_option('rmbz_referral_blacklist', []);
    if ( in_array($referrer_tel, $blacklist, true) ) return false;

    global $wpdb;
    $log_table = rmbz_referral_log_table();
    $wallets   = $wpdb->prefix . 'rmbz_wallets';

    // Convidador tem que existir como utilizador 1MZ E não estar banido
    // [1.5.133] Defesa em profundidade: se a conta do referrer está banida
    // pelo admin (is_banned=1), também não recebe comissões.
    $referrer = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, is_banned FROM $wallets WHERE user_telemovel = %s",
        $referrer_tel
    ) );
    if ( ! $referrer ) return false;
    if ( ! empty($referrer->is_banned) ) return false;

    // Evitar duplicado: já há entry para este buyer?
    $existing = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM $log_table WHERE buyer_telemovel = %s",
        $buyer_tel
    ) );
    if ( $existing > 0 ) return false;

    $wpdb->insert(
        $log_table,
        [
            'referrer_telemovel' => $referrer_tel,
            'buyer_telemovel'    => $buyer_tel,
            'commission_type'    => get_option('rmbz_referral_type', 'mt'),
            'status'             => 'pending',
            'reason'             => 'Aguarda 1º depósito aprovado + compra de plano VIP',
            'log_date'           => current_time('mysql', 1),
        ],
        ['%s','%s','%s','%s','%s','%s']
    );

    // [1.5.138] Notificar o REFERRER (não o buyer) que alguém o usou como
    // convidador. Email + sino. Template editável: referral_pending.
    if ( function_exists('rmbz_notify') ) {
        // Buscar nome do amigo para a mensagem
        $buyer_name = (string) $wpdb->get_var( $wpdb->prepare(
            "SELECT user_nome FROM $wallets WHERE user_telemovel = %s",
            $buyer_tel
        ) );
        if ( empty($buyer_name) ) $buyer_name = 'Um novo artista';

        // Mascarar tel para privacidade: +258 84 XXX 8807 -> mostra só os últimos 4
        $tel_masked = $buyer_tel;
        if ( strlen($buyer_tel) > 6 ) {
            $tel_masked = substr($buyer_tel, 0, -7) . ' ••• ' . substr($buyer_tel, -4);
        }

        rmbz_notify( $referrer_tel, 'referral_pending', [
            'nome_amigo' => $buyer_name,
            'tel_amigo'  => $tel_masked,
        ]);
    }

    return true;
}


/**
 * Hook handler: 1º depósito aprovado.
 * Chamado a partir de rmbz_processar_aprovacao_deposito (admin-handlers.php)
 * via do_action('rmbz_first_deposit_approved', $buyer, $amount).
 */
function rmbz_referral_on_first_deposit_approved( $buyer_tel, $amount ) {
    if ( empty($buyer_tel) ) return;

    global $wpdb;
    $log_table = rmbz_referral_log_table();

    $entry = $wpdb->get_row( $wpdb->prepare(
        "SELECT * FROM $log_table
         WHERE buyer_telemovel = %s AND status = 'pending'
         LIMIT 1",
        $buyer_tel
    ) );
    if ( ! $entry ) return; // sem referrer, normal

    // Marcar primeiro depósito + guardar valor para cálculo da comissão MT
    $wpdb->update(
        $log_table,
        [
            'first_deposit_approved_at' => current_time('mysql', 1),
            'total_pedido'              => (float) $amount,
        ],
        [ 'id' => $entry->id ],
        [ '%s', '%f' ],
        [ '%d' ]
    );

    // Tentar concluir (caso plan_purchased_at já esteja marcado, ex: via cupão)
    rmbz_referral_try_complete( (int) $entry->id );
}
add_action( 'rmbz_first_deposit_approved', 'rmbz_referral_on_first_deposit_approved', 10, 2 );


/**
 * Hook handler: compra de plano VIP.
 * Chamado a partir de rmbz_process_buy_vip_package (admin-handlers.php)
 * via do_action('rmbz_vip_plan_purchased', $buyer, $plan_id, $price_paid).
 */
function rmbz_referral_on_vip_plan_purchased( $buyer_tel, $plan_id, $price_paid = 0 ) {
    if ( empty($buyer_tel) ) return;

    global $wpdb;
    $log_table = rmbz_referral_log_table();

    $entry = $wpdb->get_row( $wpdb->prepare(
        "SELECT * FROM $log_table
         WHERE buyer_telemovel = %s AND status = 'pending'
         LIMIT 1",
        $buyer_tel
    ) );
    if ( ! $entry ) return;

    $wpdb->update(
        $log_table,
        [
            'plan_purchased_at' => current_time('mysql', 1),
            'order_id'          => (string) $plan_id,
        ],
        [ 'id' => $entry->id ],
        [ '%s', '%s' ],
        [ '%d' ]
    );

    rmbz_referral_try_complete( (int) $entry->id );
}
add_action( 'rmbz_vip_plan_purchased', 'rmbz_referral_on_vip_plan_purchased', 10, 3 );


/**
 * Tenta concluir um referral (paga a comissão se ambas as condições estão cumpridas).
 * Idempotente — se já está completed, não faz nada.
 *
 * @param int $log_id
 * @return bool true se completou agora, false se ainda em espera ou já estava completo
 */
function rmbz_referral_try_complete( $log_id ) {
    global $wpdb;
    $log_table = rmbz_referral_log_table();

    $entry = $wpdb->get_row( $wpdb->prepare(
        "SELECT * FROM $log_table WHERE id = %d",
        $log_id
    ) );
    if ( ! $entry ) return false;
    if ( $entry->status !== 'pending' ) return false;
    if ( empty($entry->first_deposit_approved_at) ) return false;
    if ( empty($entry->plan_purchased_at) ) return false;

    // Ambas condições cumpridas → calcular recompensa
    $type = get_option('rmbz_referral_type', 'mt');
    $reward_paid = false;
    $commission_amount = 0;
    $commission_days   = 0;

    if ( $type === 'mt' ) {
        $rate = (float) get_option('rmbz_referral_rate', 3.0);
        $commission_amount = round( ((float) $entry->total_pedido) * $rate / 100.0, 2 );

        if ( $commission_amount > 0 ) {
            $details = sprintf(
                '🎉 Comissão de convite — %s fez 1º depósito + comprou plano (taxa %s%%)',
                $entry->buyer_telemovel,
                number_format($rate, 2)
            );
            $result = rmbz_update_wallet_balance(
                $entry->referrer_telemovel,
                $commission_amount,
                'referral_bonus',
                null,
                $details
            );
            $reward_paid = ! empty($result['success']);
        }
    } else if ( $type === 'days' ) {
        $commission_days = (int) get_option('rmbz_referral_days', 5);
        if ( $commission_days > 0 ) {
            $reward_paid = rmbz_referral_grant_vip_days( $entry->referrer_telemovel, $commission_days, $entry->buyer_telemovel );
        }
    }

    if ( ! $reward_paid ) {
        $wpdb->update(
            $log_table,
            [ 'status' => 'failed', 'reason' => 'Falha a creditar recompensa' ],
            [ 'id' => $log_id ], ['%s','%s'], ['%d']
        );
        return false;
    }

    $wpdb->update(
        $log_table,
        [
            'commission_amount' => $commission_amount,
            'commission_days'   => $commission_days,
            'commission_type'   => $type,
            'status'            => 'completed',
            'reason'            => 'Comissão paga',
            'completed_at'      => current_time('mysql', 1),
        ],
        [ 'id' => $log_id ],
        [ '%f', '%d', '%s', '%s', '%s', '%s' ],
        [ '%d' ]
    );

    // [1.5.138] Notificação ao referrer via Centro (email + sino).
    // Antes usava rmbz_create_notification (função que pode não existir).
    // Agora rmbz_notify com template editável: referral_completed.
    if ( function_exists('rmbz_notify') ) {
        // Buscar nome do amigo
        $buyer_name = (string) $wpdb->get_var( $wpdb->prepare(
            "SELECT user_nome FROM {$wpdb->prefix}rmbz_wallets WHERE user_telemovel = %s",
            $entry->buyer_telemovel
        ) );
        if ( empty($buyer_name) ) $buyer_name = 'Amigo';

        $tel_masked = $entry->buyer_telemovel;
        if ( strlen($tel_masked) > 6 ) {
            $tel_masked = substr($tel_masked, 0, -7) . ' ••• ' . substr($tel_masked, -4);
        }

        // Texto da comissão consoante o tipo
        if ( $type === 'mt' ) {
            $comissao_str = number_format($commission_amount, 0, ',', '.') . ' MT';
        } else {
            $comissao_str = $commission_days . ' dia(s) VIP grátis';
        }

        rmbz_notify( $entry->referrer_telemovel, 'referral_completed', [
            'nome_amigo' => $buyer_name,
            'tel_amigo'  => $tel_masked,
            'comissao'   => $comissao_str,
        ]);
    }

    return true;
}


/**
 * Adiciona N dias à subscrição activa do referrer (ou cria uma nova se não tiver).
 * Usado quando tipo de recompensa é 'days'.
 *
 * @param string $tel
 * @param int    $days
 * @param string $reason_buyer  Telemóvel do amigo (para histórico)
 * @return bool
 */
function rmbz_referral_grant_vip_days( $tel, $days, $reason_buyer = '' ) {
    if ( empty($tel) || $days <= 0 ) return false;
    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_subscriptions';

    $now = current_time('mysql');
    $existing = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, end_date FROM $table
         WHERE user_telemovel = %s AND status = 'active'
         ORDER BY end_date DESC LIMIT 1",
        $tel
    ) );

    if ( $existing && $existing->end_date > $now ) {
        // Estende sub existente
        $new_end = date('Y-m-d H:i:s', strtotime($existing->end_date) + ($days * 86400));
        $wpdb->update( $table, [ 'end_date' => $new_end ], [ 'id' => (int) $existing->id ], ['%s'], ['%d'] );
    } else {
        // Cria nova
        $end = date('Y-m-d H:i:s', current_time('timestamp') + ($days * 86400));
        $wpdb->insert( $table, [
            'user_telemovel' => $tel,
            'start_date'     => $now,
            'end_date'       => $end,
            'status'         => 'active',
        ], ['%s','%s','%s','%s']);
    }

    return true;
}


/* ============================================================================
 * STATS para o card "Ganhe Saldo Extra"
 * ============================================================================ */

/**
 * Devolve estatísticas para mostrar no card do utilizador.
 * @return array ['count' => int, 'mt_earned' => float, 'days_earned' => int, 'pending' => int]
 */
function rmbz_referral_get_user_stats( $telemovel ) {
    global $wpdb;
    $log_table = rmbz_referral_log_table();

    $stats = [
        'count'       => 0,
        'mt_earned'   => 0.0,
        'days_earned' => 0,
        'pending'     => 0,
    ];

    if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) !== $log_table ) return $stats;

    $rows = $wpdb->get_results( $wpdb->prepare(
        "SELECT status, commission_amount, commission_days
         FROM $log_table
         WHERE referrer_telemovel = %s",
        $telemovel
    ) );

    foreach ( (array) $rows as $r ) {
        if ( $r->status === 'completed' ) {
            $stats['count']++;
            $stats['mt_earned']   += (float) $r->commission_amount;
            $stats['days_earned'] += (int) $r->commission_days;
        } else if ( $r->status === 'pending' ) {
            $stats['pending']++;
        }
    }

    return $stats;
}


/**
 * Devolve a lista detalhada de convites do utilizador (para a modal "Ver detalhes").
 */
function rmbz_referral_get_user_log( $telemovel, $limit = 50 ) {
    global $wpdb;
    $log_table = rmbz_referral_log_table();
    if ( $wpdb->get_var( "SHOW TABLES LIKE '$log_table'" ) !== $log_table ) return [];

    return (array) $wpdb->get_results( $wpdb->prepare(
        "SELECT buyer_telemovel, status, commission_amount, commission_days, commission_type,
                first_deposit_approved_at, plan_purchased_at, completed_at, log_date
         FROM $log_table
         WHERE referrer_telemovel = %s
         ORDER BY log_date DESC
         LIMIT %d",
        $telemovel, (int) $limit
    ) );
}
