from typing import Optional

from solders.pubkey import Pubkey
from solana.transaction import Transaction

import dexteritysdk.constant_fees.instructions as ixs
import dexteritysdk.program_ids as pids
from dexteritysdk.dex.addrs import (
    get_trader_fee_state_acct,
    get_trader_risk_group_addr,
    get_fee_model_configuration_addr,
)
from dexteritysdk.utils.solana import (
    actionify,
)


@actionify
def update_fees(
    payer: Pubkey,
    market_product_group: Pubkey,
    maker_fee_bps: int,
    taker_fee_bps: int,
    fee_model_config_acct: Optional[Pubkey] = None,
    program_id: Pubkey = pids.CONSTANT_FEES_MODEL_PROGRAM_ID,
):
    if fee_model_config_acct is None:
        fee_model_config_acct = get_fee_model_configuration_addr(
            market_product_group, program_id
        )

    return Transaction(fee_payer=payer).add(
        ixs.update_fees_ix(
            payer=payer,
            fee_model_config_acct=fee_model_config_acct,
            market_product_group=market_product_group,
            system_program=pids.SYSTEM_PROGRAM_ID,
            maker_fee_bps=maker_fee_bps,
            taker_fee_bps=taker_fee_bps,
            program_id=program_id,
        )
    )


@actionify
def initialize_trader_fee_acct(
    payer: Pubkey,
    market_product_group: Pubkey,
    program_id: Pubkey = pids.CONSTANT_FEES_MODEL_PROGRAM_ID,
    trader_risk_group: Optional[Pubkey] = None,
    system_program: Optional[Pubkey] = pids.SYSTEM_PROGRAM_ID,
    fee_model_config_acct: Optional[Pubkey] = None,
):
    if trader_risk_group is None:
        trader_risk_group = get_trader_risk_group_addr(
            payer,
            market_product_group,
        )

    if fee_model_config_acct is None:
        fee_model_config_acct = get_fee_model_configuration_addr(
            market_product_group,
            program_id,
        )

    trader_fee_acct = get_trader_fee_state_acct(
        payer,
        market_product_group,
        program_id,
    )

    return Transaction(fee_payer=payer).add(
        ixs.initialize_trader_acct_ix(
            payer=payer,
            fee_model_config_acct=fee_model_config_acct,
            trader_fee_acct=trader_fee_acct,
            market_product_group=market_product_group,
            trader_risk_group=trader_risk_group,
            system_program=system_program,
            program_id=program_id,
        )
    )
