<?php
// includes/wallet-functions.php

/**
 * Funções de Gestão da Carteira Digital do 1MZ For Artists.
 * Lida com saldos, transações, bloqueios de fundos e histórico.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Acesso direto bloqueado
}

/**
 * Obtém o saldo TOTAL da carteira do utilizador.
 */
function rmbz_get_wallet_balance_by_phone( $telemovel ) {
    if ( empty($telemovel) ) return 0.00;
    
    global $wpdb;
    $table_name = $wpdb->prefix . 'rmbz_wallets';
    $balance = $wpdb->get_var( $wpdb->prepare( "SELECT balance FROM $table_name WHERE user_telemovel = %s", $telemovel ) );

    return $balance ? (float)$balance : 0.00;
}

/**
 * Obtém apenas o saldo RETIRÁVEL (ignorando saldos promocionais bloqueados).
 */
function rmbz_get_withdrawable_balance( $telemovel ) {
    if ( empty($telemovel) ) return 0.00;

    global $wpdb;
    $transactions_table = $wpdb->prefix . 'rmbz_wallet_transactions';
    $now_gmt = current_time('mysql', 1);

    // 1. Obter o saldo total
    $total_balance = rmbz_get_wallet_balance_by_phone( $telemovel );

    // 2. Calcular a soma de fundos BLOQUEADOS (Saldos Promocionais)
    $locked_funds_sum = (float) $wpdb->get_var( $wpdb->prepare(
        "SELECT SUM(amount) FROM {$transactions_table} 
         WHERE user_telemovel = %s 
         AND is_unlocked = 0 
         AND unlock_date > %s",
        $telemovel,
        $now_gmt
    ) );

    // 3. Subtrair os bloqueios do saldo total
    $withdrawable_balance = $total_balance - $locked_funds_sum;

    return max(0.00, $withdrawable_balance);
}

/**
 * Atualiza o saldo do utilizador e regista a transação com inteligência de Bónus/Abatimento.
 *
 * [BUG-WB1] Hardening 2026-04: o saldo era lido, modificado em PHP e
 * regravado, sem qualquer protecção contra concorrência. Em caso de cliques
 * paralelos / requests simultâneos, o utilizador podia gastar mais do que
 * tinha (TOCTOU). Agora envolvemos a lógica em GET_LOCK por utilizador.
 */
function rmbz_update_wallet_balance($user_telemovel, $amount, $type, $project_id = null, $details = '', $is_unlocked = 1, $unlock_date = null) {
    global $wpdb;

    if ( empty($user_telemovel) ) {
        return ['success' => false, 'error' => 'Telemovel inválido.'];
    }

    $table_wallets = $wpdb->prefix . 'rmbz_wallets';
    $table_transactions = $wpdb->prefix . 'rmbz_wallet_transactions';

    // [BUG-WB1] Lock por carteira para serializar todas as escritas.
    $lock_name = 'rmbz_wallet_' . md5((string)$user_telemovel);
    $got_lock = (int) $wpdb->get_var( $wpdb->prepare("SELECT GET_LOCK(%s, 5)", $lock_name) );
    if ( ! $got_lock ) {
        return ['success' => false, 'error' => 'Sistema ocupado, tente novamente.'];
    }

    try {
        $current_balance = $wpdb->get_var( $wpdb->prepare("SELECT balance FROM {$table_wallets} WHERE user_telemovel = %s", $user_telemovel) );
        if ( $current_balance === null ) return ['success' => false, 'error' => 'Carteira não encontrada.'];

        $new_balance = (float)$current_balance + (float)$amount;

        // Bloqueia se o saldo final for negativo, a menos que seja um débito forçado pelo admin
        if ( $new_balance < 0 && $type !== 'admin_debit' ) return ['success' => false, 'error' => 'Saldo insuficiente.'];

        // LÓGICA DE ABATIMENTO DE BÓNUS
        // Se o artista gastar dinheiro (débito), descontamos do saldo promocional (bloqueado) primeiro!
        if ($amount < 0) {
            $locked_sum = (float) $wpdb->get_var($wpdb->prepare("SELECT SUM(amount) FROM {$table_transactions} WHERE user_telemovel = %s AND is_unlocked = 0 AND unlock_date > NOW()", $user_telemovel));

            if ($locked_sum > 0) {
                $abatimento = max($amount, -$locked_sum); // Consome apenas o necessário do saldo promocional
                $wpdb->insert(
                    $table_transactions,
                    [
                        'user_telemovel'   => $user_telemovel,
                        'amount'           => $abatimento,
                        'type'             => 'lock_adjustment',
                        'details'          => 'Uso de saldo promocional na plataforma',
                        'transaction_date' => current_time('mysql'),
                        'is_unlocked'      => 0,
                        'unlock_date'      => '2099-12-31 23:59:59'
                    ],
                    ['%s', '%f', '%s', '%s', '%s', '%d', '%s']
                );
            }
        }

        // Atualizar saldo final na tabela de carteiras
        $updated = $wpdb->update(
            $table_wallets,
            [ 'balance' => $new_balance, 'last_updated' => current_time('mysql') ],
            [ 'user_telemovel' => $user_telemovel ],
            [ '%f', '%s' ], [ '%s' ]
        );

        if ( $updated !== false ) {
            // Regista a transação principal
            $wpdb->insert(
                $table_transactions,
                [
                    'user_telemovel'   => $user_telemovel,
                    'amount'           => $amount,
                    'type'             => $type,
                    'project_id'       => $project_id,
                    'details'          => $details,
                    'transaction_date' => current_time('mysql'),
                    'is_unlocked'      => $is_unlocked,
                    'unlock_date'      => $unlock_date
                ],
                ['%s', '%f', '%s', '%d', '%s', '%s', '%d', '%s']
            );
            return ['success' => true, 'new_balance' => $new_balance];
        }

        return ['success' => false, 'error' => 'Falha ao atualizar a base de dados.'];
    } finally {
        $wpdb->query( $wpdb->prepare("SELECT RELEASE_LOCK(%s)", $lock_name) );
    }
}

/**
 * Regista tentativas e comissões do sistema de referências/convites.
 */
function rmbz_log_referral_attempt($reference_id, $project_id, $buyer_telemovel, $referrer_telemovel, $total_pago, $commission_amount) {
    global $wpdb;
    $log_table = $wpdb->prefix . 'rmbz_referral_log';
    
    $payment_success = false;
    $reason = '';

    $wallets_table = $wpdb->prefix . 'rmbz_wallets';
    $referrer_wallet = $wpdb->get_row( $wpdb->prepare( "SELECT id FROM $wallets_table WHERE user_telemovel = %s", $referrer_telemovel ) );

    if ( ! $referrer_wallet ) { 
        $reason = 'Carteira do convidador não encontrada. '; 
    } else { 
        $reason = 'Carteira encontrada. Processando... '; 
    }

    $details = 'Comissão de convite (' . $reference_id . ')';
    $payment_result = rmbz_update_wallet_balance( $referrer_telemovel, $commission_amount, 'referral_bonus', $project_id, $details );

    if ( $payment_result['success'] ) { 
        $status = 'success'; 
        $reason .= 'Creditado com sucesso.'; 
        $payment_success = true; 
    } else { 
        $status = 'failed'; 
        $reason .= 'Falha: ' . $payment_result['error']; 
        $payment_success = false; 
    }

    $wpdb->insert(
        $log_table,
        [
            'order_id'           => $reference_id,
            'rifa_id'            => $project_id,
            'buyer_telemovel'    => $buyer_telemovel,
            'referrer_telemovel' => $referrer_telemovel,
            'total_pedido'       => $total_pago,
            'commission_amount'  => $commission_amount,
            'status'             => $status,
            'reason'             => $reason,
            'log_date'           => current_time( 'mysql', 1 )
        ],
        [ '%s', '%d', '%s', '%s', '%f', '%f', '%s', '%s', '%s' ]
    );

    return $payment_success;
}

/**
 * Obtém o valor debitado da carteira com base numa referência específica.
 */
function rmbz_get_wallet_debit_amount_by_reference( $reference_id, $telemovel ) {
    global $wpdb;
    $transactions_table = $wpdb->prefix . 'rmbz_wallet_transactions';
    
    $amount = $wpdb->get_var( $wpdb->prepare(
        "SELECT ABS(amount) FROM {$transactions_table} 
         WHERE user_telemovel = %s AND amount < 0 AND details LIKE %s 
         ORDER BY transaction_id DESC LIMIT 1",
        $telemovel, '%' . $wpdb->esc_like($reference_id) . '%'
    ) );
    return $amount ? (float)$amount : 0.00;
}

/**
 * Obtém os dados e estatísticas do painel de Criador (referências).
 */
function rmbz_get_creator_dashboard_data( $telemovel ) {
    global $wpdb;
    $log_table = $wpdb->prefix . 'rmbz_referral_log';

    $total_referrals = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(DISTINCT buyer_telemovel) FROM {$log_table} WHERE referrer_telemovel = %s AND status = 'success'", $telemovel) );
    $total_commission_paid = (float) $wpdb->get_var( $wpdb->prepare("SELECT SUM(commission_amount) FROM {$log_table} WHERE referrer_telemovel = %s AND status = 'success'", $telemovel) );
    $detailed_log = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$log_table} WHERE referrer_telemovel = %s ORDER BY log_date DESC LIMIT 50", $telemovel) );

    return [
        'total_referrals'         => $total_referrals,
        'total_commission_paid'   => $total_commission_paid,
        'detailed_log'            => $detailed_log,
        'total_sales_generated'   => 0, 
        'total_commission_failed' => 0
    ];
}