import os
from flask import Flask, request, jsonify
from ravencoin.rpc import RavenProxy
from dotenv import load_dotenv
import re
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
import redis

# Load environment variables
load_dotenv()  # Load environment variables from .env file
api_key = os.getenv('RVN_API_KEY')
if not api_key:
    raise ValueError("API Key not found in environment variables")

print(f"API Key loaded: {api_key}")

app = Flask(__name__)

# Set up Redis for rate limiting
redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379/0')  # Default Redis URL
r = redis.from_url(redis_url)

# Initialize Flask-Limiter with Redis storage
limiter = Limiter(get_remote_address, app=app, storage_uri=redis_url)

# Initialize Ravencoin RPC Proxy
rpc_user = os.getenv('RVN_RPC_USER')
rpc_password = os.getenv('RVN_RPC_PASSWORD')
rpc_port = int(os.getenv('RVN_RPC_PORT', 8766))  # Default to 8766 if not provided
rvn = RavenProxy(service_port=rpc_port, username=rpc_user, password=rpc_password)

def is_valid_rvn_address(address):
    """Validate the provided Ravencoin address."""
    return bool(re.match(r'^[Rr][a-km-zA-HJ-NP-Z1-9]{25,34}$', address))

@app.route('/', methods=['POST'])
@limiter.limit("10 per minute")  # Rate limit for RVN payments
def reward_player():
    req_data = request.get_json()
    provided_api_key = request.headers.get('X-API-KEY')

    # Check for valid API key
    if provided_api_key != api_key:
        return jsonify({'error': 'Unauthorized'}), 403

    # Check for missing fields in the request
    if 'player_address' not in req_data or 'asset_name' not in req_data:
        return jsonify({'error': 'Missing player_address or asset_name'}), 400

    player_address = req_data['player_address']
    asset_name = req_data['asset_name']
    
    # Get amount from request or use default
    amount = req_data.get('amount', 100)  # Use provided amount or default to 100

    # Validate the provided Ravencoin address
    if not is_valid_rvn_address(player_address):
        return jsonify({'error': 'Invalid Ravencoin address'}), 400

    try:
        # Log the transaction attempt
        print(f"Attempting to send {amount} of {asset_name} to {player_address}")

        # Handle RVN vs Asset payments differently
        if asset_name.upper() == 'RVN':
            # For RVN payments, use amount directly as RVN (no satoshi conversion)
            rvn_amount = float(amount)
            print(f"Processing RVN payment: {rvn_amount} RVN to {player_address}")
            
            # Get network info for minimum fee requirements
            try:
                network_info = rvn.getnetworkinfo()
                min_relay_fee = network_info.get('relayfee', 0.00001)
                print(f"Node minimum relay fee: {min_relay_fee}")
                
                # Ensure amount meets minimum requirements
                if rvn_amount < min_relay_fee:
                    print(f"Amount {rvn_amount} below minimum {min_relay_fee}, adjusting to minimum")
                    rvn_amount = max(min_relay_fee * 10, 0.001)  # Use 10x minimum or 0.001, whichever is higher
                    
            except Exception as e:
                print(f"Could not get network info: {e}")
                # Use a safe minimum if we can't get network info
                if rvn_amount < 0.001:
                    print(f"Using fallback minimum: adjusting {rvn_amount} to 0.001 RVN")
                    rvn_amount = 0.001
            
            print(f"Final RVN amount: {rvn_amount}")
            txid = rvn.sendtoaddress(player_address, rvn_amount)
            
        else:
            # For assets, use transfer method
            print(f"Sending {amount} units of asset {asset_name}")
            txid = rvn.transfer(asset_name, amount, player_address)

        # If txid is in bytes, convert it to a hex string
        if isinstance(txid, bytes):
            txid = txid.hex()

        print(f"Transaction successful! TXID: {txid}")
        return jsonify({'txid': txid}), 200
        
    except Exception as e:
        # Return error message if something goes wrong
        error_msg = str(e)
        print(f"Transaction failed: {error_msg}")
        return jsonify({'error': error_msg}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=30992, debug=True)
