use crate::events::OrderSide;

#[derive(Debug, Clone, Copy)]
pub struct TradingCost {
    pub commission: f64,
    pub stamp_tax: f64,
}

impl TradingCost {
    pub fn total(self) -> f64 {
        self.commission + self.stamp_tax
    }
}

pub trait CostModel {
    fn calculate(&self, side: OrderSide, gross_amount: f64) -> TradingCost;
}

#[derive(Debug, Clone, Copy)]
pub struct ChinaAShareCostModel {
    pub commission_rate: f64,
    pub stamp_tax_rate: f64,
    pub minimum_commission: f64,
}

impl Default for ChinaAShareCostModel {
    fn default() -> Self {
        Self {
            commission_rate: 0.0003,
            stamp_tax_rate: 0.001,
            minimum_commission: 5.0,
        }
    }
}

impl CostModel for ChinaAShareCostModel {
    fn calculate(&self, side: OrderSide, gross_amount: f64) -> TradingCost {
        if gross_amount <= 0.0 {
            return TradingCost {
                commission: 0.0,
                stamp_tax: 0.0,
            };
        }

        let commission = (gross_amount * self.commission_rate).max(self.minimum_commission);
        let stamp_tax = match side {
            OrderSide::Buy => 0.0,
            OrderSide::Sell => gross_amount * self.stamp_tax_rate,
        };

        TradingCost {
            commission,
            stamp_tax,
        }
    }
}
