"""Debt token processor for revision 1."""

import degenbot.aave.libraries
from degenbot.aave.processors.base import (
    DebtBurnEvent,
    DebtMintEvent,
    DebtTokenProcessor,
    MathLibraries,
    ScaledTokenBurnResult,
    ScaledTokenMintResult,
)


class DebtV1Processor(DebtTokenProcessor):
    """Processor for VToken revision 1."""

    revision = 1

    def __init__(self) -> None:
        self._math_libs = MathLibraries(
            wad_ray=degenbot.aave.libraries.wad_ray_math,
            percentage=degenbot.aave.libraries.percentage_math,
        )

    def get_math_libraries(self) -> MathLibraries:
        """Get the math libraries for this revision."""
        return self._math_libs

    def process_mint_event(
        self,
        event_data: DebtMintEvent,
        previous_balance: int,  # noqa: ARG002
        previous_index: int,  # noqa: ARG002
        scaled_delta: int | None = None,  # noqa: ARG002
    ) -> ScaledTokenMintResult:
        """
        Process a debt mint event.

        Mint events can be triggered by:
        - BORROW: value > balance_increase
        - REPAY: balance_increase > value (interest accrual)

        Args:
            event_data: The mint event data
            previous_balance: The user's balance before this event
            previous_index: The index at previous_balance calculation
            scaled_delta: Unused for revisions 1-3 (calculated from event data)

        Returns:
            MintResult with balance_delta, new_index, and is_repay flag
        """
        wad_ray_math = self._math_libs["wad_ray"]

        if event_data.value >= event_data.balance_increase:
            # BORROW path: emitted in _mintScaled
            if event_data.scaled_amount is not None:
                # Use pre-calculated scaled amount from BORROW event
                balance_delta = event_data.scaled_amount
            else:
                # Fallback: calculate from event data
                # Solidity: uint256 amountToMint = amount + balanceIncrease;
                requested_amount = event_data.value - event_data.balance_increase
                balance_delta = wad_ray_math.ray_div(
                    a=requested_amount,
                    b=event_data.index,
                )
            is_repay = False
        else:
            # REPAY path: emitted in _burnScaled
            # The Mint event is emitted when interest > repayment amount.
            # The net balance change is just burning the scaled repayment amount.
            # amount = balanceIncrease - value (from Mint event)
            amount_repaid = event_data.balance_increase - event_data.value
            balance_delta = -wad_ray_math.ray_div(
                a=amount_repaid,
                b=event_data.index,
            )
            is_repay = True
        return ScaledTokenMintResult(
            balance_delta=balance_delta,
            new_index=event_data.index,
            is_repay=is_repay,
        )

    def calculate_scaled_amount(self, raw_amount: int, index: int) -> int:
        """
        Calculate scaled amount from raw underlying amount.

        Uses standard ray_div (half up rounding) to match revision 1-3 vToken
        behavior.

        Args:
            raw_amount: The raw underlying token amount
            index: The current borrow index

        Returns:
            The scaled amount
        """
        return self._math_libs["wad_ray"].ray_div(
            a=raw_amount,
            b=index,
        )

    def calculate_mint_scaled_amount(self, raw_amount: int, index: int) -> int:
        """
        Calculate scaled amount for mint operations.

        For V1, uses the same calculation as burn (standard ray_div).

        Args:
            raw_amount: The raw underlying token amount
            index: The current borrow index

        Returns:
            The scaled amount
        """
        return self.calculate_scaled_amount(raw_amount=raw_amount, index=index)

    def process_burn_event(
        self,
        event_data: DebtBurnEvent,
        previous_balance: int,  # noqa: ARG002
        previous_index: int,  # noqa: ARG002
        scaled_delta: int | None = None,
    ) -> ScaledTokenBurnResult:
        """
        Process a debt burn event.

        Burn events are triggered by REPAY operations.

        Args:
            event_data: The burn event data
            previous_balance: The user's balance before this event
            previous_index: The index at previous_balance calculation
            scaled_delta: Pre-calculated scaled amount from original paybackAmount.
                When provided, used directly to avoid double-scaling.

        Returns:
            BurnResult with balance_delta and new_index
        """
        if scaled_delta is not None:
            # Use pre-calculated scaled amount from paybackAmount
            # This is critical for REPAY with Mint event when interest > repayment
            return ScaledTokenBurnResult(
                balance_delta=-scaled_delta,
                new_index=event_data.index,
            )

        # Fallback: calculate from event data (for standard Burn events)
        wad_ray_math = self._math_libs["wad_ray"]

        # uint256 amountToBurn = amount - balanceIncrease;
        requested_amount = event_data.value + event_data.balance_increase

        # uint256 amountScaled = amount.rayDiv(index);
        balance_delta = -wad_ray_math.ray_div(
            a=requested_amount,
            b=event_data.index,
        )

        return ScaledTokenBurnResult(
            balance_delta=balance_delta,
            new_index=event_data.index,
        )
