Documentation
use crate::wechat::Wechat;
use json::{JsonValue};

pub mod alipay;
pub mod wechat;

#[derive(Clone)]
pub enum Pay {
    Wechat(Wechat),
    Alipay,
}

impl Pay {
    pub fn new(data: JsonValue) -> Self {
        match data["mode"].as_str().unwrap_or("") {
            "wechat" => Pay::Wechat(Wechat {
                appid: data["appid"].to_string(),
                mchid: data["mchid"].to_string(),
                serial_no: data["serial_no"].to_string(),
                cert_path: data["cert_path"].to_string(),
                secret: data["secret"].to_string(),
            }),
            _ => Pay::Alipay,
        }
    }
}
impl PayMode for Pay {
    fn login(&self, code: &str) -> Result<JsonValue, String> {
        match self {
            Self::Wechat(e) => e.login(code),
            Self::Alipay => Err("Alipay alipay".to_string()),
        }
    }

    /// jsapi 支付
    fn jsapi(
        &mut self,
        sub_mchid: &str,
        out_trade_no: &str,
        description: &str,
        total_fee: f64,
        notify_url: &str,
        sp_openid: &str,
    ) -> Result<JsonValue, String> {
        match self {
            Self::Wechat(e) => e.jsapi(
                sub_mchid,
                out_trade_no,
                description,
                total_fee,
                notify_url,
                sp_openid,
            ),
            Self::Alipay => Err("Alipay alipay".to_string()),
        }
    }

    fn order_trade(&mut self, out_trade_no: &str, sub_mchid: &str) -> Result<JsonValue, String> {
        match self {
            Self::Wechat(e) => e.order_trade(
                out_trade_no,
                sub_mchid,
            ),
            Self::Alipay => Err("Alipay alipay".to_string()),
        }
    }

    fn refunds(&mut self, sub_mchid: &str, out_trade_no: &str, transaction_id: &str, out_refund_no: &str, amount: f64, total: f64, currency: &str) -> Result<JsonValue, String> {
        match self {
            Self::Wechat(e) => e.refunds(
                sub_mchid,
                out_trade_no,
                transaction_id,
                out_refund_no,
                amount,
                total,
                currency
            ),
            Self::Alipay => Err("Alipay alipay".to_string()),
        }
    }
}

pub trait PayMode {
    fn login(&self, code: &str) -> Result<JsonValue, String>;
    /// JSAPI 支付
    /// * out_trade_no 商户订单号
    /// * sub_mchid 子商户号
    /// * description 商品名称
    /// * total_fee 支付金额
    /// * notify_url 通知地址
    /// * sp_openid 支付客户ID
    fn jsapi(
        &mut self,
        sub_mchid: &str,
        out_trade_no: &str,
        description: &str,
        total_fee: f64,
        notify_url: &str,
        sp_openid: &str,
    ) -> Result<JsonValue, String>;
    /// 订单查询
    /// * out_trade_no 商户订单号
    /// * sub_mchid 子商户号
    fn order_trade(
        &mut self,
        out_trade_no: &str,
        sub_mchid: &str,
    ) -> Result<JsonValue, String>;
    /// 订单退款
    #[allow(clippy::too_many_arguments)]
    fn refunds(&mut self,
               sub_mchid: &str,
               out_trade_no: &str,
               transaction_id: &str,
               out_refund_no: &str,
               amount: f64,
               total: f64,
               currency: &str,
    ) -> Result<JsonValue, String>;
}