"""
Background jobs for wallet operations.

- Auto-sweep: Transfer excess funds (over $50 cap) to user's sweep address
- Deposit detection: Monitor for incoming deposits and credit user ledgers
- Withdrawal processing: Process pending withdrawal requests
"""
import logging
import time
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .wallet_manager import WalletManager

logger = logging.getLogger(__name__)

# Job intervals in seconds
AUTO_SWEEP_INTERVAL = 300  # 5 minutes
DEPOSIT_CHECK_INTERVAL = 60  # 1 minute
WITHDRAWAL_PROCESS_INTERVAL = 30  # 30 seconds


class WalletBackgroundJobs:
    """
    Manages background jobs for wallet operations.
    Uses eventlet for async execution compatible with Flask-SocketIO.
    """

    def __init__(self, wallet_manager: 'WalletManager', socketio=None):
        self.wallet_manager = wallet_manager
        self.socketio = socketio
        self._running = False
        self._jobs_started = False

    def start_all_jobs(self):
        """Start all background jobs."""
        if self._jobs_started:
            logger.warning("Wallet background jobs already started")
            return

        self._running = True
        self._jobs_started = True

        if self.socketio:
            # Use SocketIO's background task mechanism
            self.socketio.start_background_task(self._auto_sweep_loop)
            self.socketio.start_background_task(self._deposit_detection_loop)
            self.socketio.start_background_task(self._withdrawal_processing_loop)
            logger.info("Wallet background jobs started via SocketIO")
        else:
            # Fallback to eventlet directly
            import eventlet
            eventlet.spawn(self._auto_sweep_loop)
            eventlet.spawn(self._deposit_detection_loop)
            eventlet.spawn(self._withdrawal_processing_loop)
            logger.info("Wallet background jobs started via eventlet")

    def stop_all_jobs(self):
        """Stop all background jobs."""
        self._running = False
        logger.info("Wallet background jobs stopping...")

    # === Auto-Sweep Job ===

    def _auto_sweep_loop(self):
        """Background loop for auto-sweep functionality."""
        logger.info("Auto-sweep job started")
        while self._running:
            try:
                self._process_auto_sweeps()
            except Exception as e:
                logger.error(f"Auto-sweep error: {e}")
            self._sleep(AUTO_SWEEP_INTERVAL)

    def _process_auto_sweeps(self):
        """Check all wallets and sweep excess funds."""
        try:
            # Get all wallets that might need sweeping
            wallets = self.wallet_manager.get_wallets_over_cap()

            for wallet in wallets:
                user_id = wallet['user_id']
                balance = wallet['balance']
                sweep_address = wallet['sweep_address']
                cap = self.wallet_manager.BALANCE_CAP_SATOSHIS

                if not sweep_address:
                    logger.warning(f"User {user_id} has no sweep address configured")
                    continue

                excess = balance - cap
                if excess <= 0:
                    continue

                # Keep a small buffer (1000 sats) to avoid sweeping tiny amounts
                if excess < 1000:
                    continue

                logger.info(f"Auto-sweeping {excess} satoshis for user {user_id}")

                # Perform the sweep
                result = self.wallet_manager.auto_sweep(user_id, excess)
                if result.get('success'):
                    logger.info(f"Auto-sweep successful for user {user_id}: {result.get('tx_hash', 'simulated')}")
                else:
                    logger.error(f"Auto-sweep failed for user {user_id}: {result.get('error')}")

        except Exception as e:
            logger.error(f"Error processing auto-sweeps: {e}")

    # === Deposit Detection Job ===

    def _deposit_detection_loop(self):
        """Background loop for deposit detection."""
        logger.info("Deposit detection job started")
        while self._running:
            try:
                self._check_for_deposits()
            except Exception as e:
                logger.error(f"Deposit detection error: {e}")
            self._sleep(DEPOSIT_CHECK_INTERVAL)

    def _check_for_deposits(self):
        """Check all wallet addresses for new deposits."""
        try:
            # Include disabled wallets so incoming deposits are still credited.
            wallets = self.wallet_manager.get_wallets_for_deposit_monitoring()

            for wallet in wallets:
                user_id = wallet['user_id']
                fee_address = wallet['fee_address']
                network = wallet['network']

                # Check for new deposits at the fee address
                new_deposits = self.wallet_manager.check_address_for_deposits(
                    user_id=user_id,
                    address=fee_address,
                    network=network
                )

                for deposit in new_deposits:
                    logger.info(f"New deposit detected for user {user_id}: "
                               f"{deposit['amount_satoshis']} sats, tx: {deposit['tx_hash']}")

        except Exception as e:
            logger.error(f"Error checking for deposits: {e}")

    # === Withdrawal Processing Job ===

    def _withdrawal_processing_loop(self):
        """Background loop for processing pending withdrawals."""
        logger.info("Withdrawal processing job started")
        while self._running:
            try:
                self._process_pending_withdrawals()
            except Exception as e:
                logger.error(f"Withdrawal processing error: {e}")
            self._sleep(WITHDRAWAL_PROCESS_INTERVAL)

    def _process_pending_withdrawals(self):
        """Process all pending withdrawal requests."""
        try:
            # Get pending withdrawals (status = 'reserved')
            pending = self.wallet_manager.get_pending_withdrawals()

            for withdrawal in pending:
                withdrawal_id = withdrawal['id']
                user_id = withdrawal['user_id']
                amount = withdrawal['amount_satoshis']
                destination = withdrawal['destination_address']

                logger.info(f"Processing withdrawal {withdrawal_id} for user {user_id}: "
                           f"{amount} sats to {destination}")

                # Process the withdrawal
                result = self.wallet_manager.process_withdrawal(withdrawal_id)

                if result.get('success'):
                    logger.info(f"Withdrawal {withdrawal_id} completed: {result.get('tx_hash', 'simulated')}")
                else:
                    logger.error(f"Withdrawal {withdrawal_id} failed: {result.get('error')}")

        except Exception as e:
            logger.error(f"Error processing withdrawals: {e}")

    def _sleep(self, seconds):
        """Sleep that respects the running flag and works with eventlet."""
        import eventlet
        # Sleep in small increments to allow quick shutdown
        remaining = seconds
        while remaining > 0 and self._running:
            sleep_time = min(remaining, 5)
            eventlet.sleep(sleep_time)
            remaining -= sleep_time
