<?php
/**
 * 1MZ For Artists — API Helpers
 *
 * Funções utilitárias para os controllers: formatação de respostas,
 * normalização de telemovel, hashing de refresh tokens.
 *
 * @package 1MZ_For_Artists
 * @since   1.6.0
 */

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

/**
 * Resposta de sucesso uniforme.
 *
 * @param mixed $data
 * @param int   $status HTTP status.
 * @return WP_REST_Response
 */
function rmbz_api_ok( $data = null, $status = 200 ) {
    return new WP_REST_Response( [
        'success' => true,
        'data'    => $data,
    ], $status );
}

/**
 * Resposta de erro uniforme. Aceita WP_Error ou string.
 *
 * @param string|WP_Error $error
 * @param int             $status
 * @param string          $code
 * @return WP_REST_Response
 */
function rmbz_api_error( $error, $status = 400, $code = 'error', $extra = null ) {
    if ( is_wp_error( $error ) ) {
        $data = $error->get_error_data();
        $status = is_array( $data ) && ! empty( $data['status'] ) ? (int) $data['status'] : $status;
        $code = $error->get_error_code() ?: $code;
        $message = $error->get_error_message();
    } else {
        $message = (string) $error;
    }

    $error_payload = [
        'code'    => $code,
        'message' => $message,
    ];

    // [1.6.25] Payload extra opcional — para erros estruturados que a app
    // precisa de mostrar ao user de forma rica (ex: lista de permissões
    // que se perderiam num downgrade). Backward-compatible: null = null.
    if ( is_array( $extra ) && ! empty( $extra ) ) {
        $error_payload['extra'] = $extra;
    }

    return new WP_REST_Response( [
        'success' => false,
        'error'   => $error_payload,
    ], $status );
}

/**
 * Normaliza um telemovel para o formato +258XXXXXXXXX.
 *
 * Mesma lógica usada no resto do plugin (rmbz_verify_recovery_account).
 *
 * @param string $input
 * @return string
 */
function rmbz_api_normalize_telemovel( $input ) {
    $clean = preg_replace( '/\s+/', '', (string) $input );
    if ( strpos( $clean, '+258' ) === 0 ) {
        return $clean;
    }
    if ( strpos( $clean, '258' ) === 0 ) {
        return '+' . $clean;
    }
    return '+258' . $clean;
}

/**
 * Valida o formato de telemovel moçambicano.
 *
 * @param string $telemovel Já normalizado.
 * @return bool
 */
function rmbz_api_is_valid_telemovel( $telemovel ) {
    // +258 seguido de 9 dígitos (rede móvel)
    return (bool) preg_match( '/^\+258\d{9}$/', $telemovel );
}

/**
 * Hash determinístico para guardar refresh tokens em DB.
 *
 * Não queremos guardar o token raw — se a DB vazar, todos os tokens são
 * inutilizáveis. Usamos sha256 do token (não bcrypt, porque precisamos de
 * lookup por hash no login).
 *
 * @param string $token
 * @return string
 */
function rmbz_api_hash_refresh_token( $token ) {
    return hash( 'sha256', $token . '|' . RMBZ_API_JWT_SECRET );
}

/**
 * Gera um refresh token criptograficamente forte.
 *
 * @return string 64 chars hex (256 bits de entropia).
 */
function rmbz_api_generate_refresh_token() {
    return bin2hex( random_bytes( 32 ) );
}

/**
 * Formata uma carteira para a API.
 */
function rmbz_api_format_wallet( $telemovel ) {
    global $wpdb;
    $w = $wpdb->get_row( $wpdb->prepare(
        "SELECT user_telemovel, user_nome, user_email, user_provincia, balance, is_creator, last_updated
         FROM {$wpdb->prefix}rmbz_wallets WHERE user_telemovel = %s",
        $telemovel
    ) );
    if ( ! $w ) {
        return null;
    }

    $withdrawable = function_exists( 'rmbz_get_withdrawable_balance' )
        ? rmbz_get_withdrawable_balance( $telemovel )
        : (float) $w->balance;

    // [1.6.118.7] Account status — usado pelo app para detectar
    // contas expiradas (soft delete pelo CRON first-deposit-expiry).
    // Valores: 'active' (default) | 'expired' (soft delete, com conteúdo).
    // Hard delete não chega aqui — user já não existe → /auth/me retorna 404.
    $account_status = 'active';
    $user_obj = get_user_by( 'login', $telemovel );
    if ( $user_obj ) {
        $meta = get_user_meta( $user_obj->ID, 'rmbz_account_status', true );
        if ( $meta === 'expired' ) {
            $account_status = 'expired';
        }
    }

    return [
        'telemovel'           => $w->user_telemovel,
        'nome'                => $w->user_nome,
        'email'               => $w->user_email,
        'provincia'           => $w->user_provincia,
        'is_creator'          => (bool) $w->is_creator,
        'balance_total'       => (float) $w->balance,
        'balance_withdrawable' => (float) $withdrawable,
        'currency'            => 'MZN',
        'updated_at'          => mysql_to_rfc3339( $w->last_updated ),
        'account_status'      => $account_status,
    ];
}
