#[derive(Clone, Debug)]
pub struct Transactions<'a> {
    api: &'a crate::Api,
    access_token: &'a crate::AccessToken,
}

impl<'a> Transactions<'a> {
    pub fn new(api: &'a crate::Api, access_token: &'a crate::AccessToken) -> Self {
        Self { api, access_token }
    }

    pub fn find_by_id(&self, id: u32) -> crate::Result<crate::Transaction> {
        self.api.transactions_get(id, self.access_token)
    }

    pub fn find_by_internal_id(&self, internal_id: u32) -> crate::Result<crate::Transaction> {
        self.api
            .transactions_get_by_internal_id(internal_id, self.access_token)
    }

    pub fn find_by_code(&self, code: &str) -> crate::Result<crate::Transaction> {
        self.api.transactions_get_by_code(code, self.access_token)
    }

    pub fn history(&self, filter: &Filter) -> crate::Result<Vec<crate::Transaction>> {
        self.api.transactions_history(filter, self.access_token)
    }

    pub fn refund(&self, id: u32, amount: Option<f32>) -> crate::Result {
        let payload = if let Some(amount) = amount {
            ureq::json!({
                "amount": amount,
            })
        } else {
            ureq::json!({})
        };

        self.api
            .transactions_refund(id, payload, self.access_token)
    }

    pub fn receipt(&self, id: u32, merchant_id: u32) -> crate::Result<crate::Receipt> {
        self.api
            .transactions_get_receipt(id, merchant_id, self.access_token)
    }
}

#[derive(Clone, Debug, Default)]
pub struct Filter {
    order: Option<String>,
    limit: Option<u32>,
    user_id: Option<u32>,
    users: Vec<u32>,
    statuses: Vec<String>,
    payment_types: Vec<String>,
    types: Vec<String>,
    changes_since: Option<String>,
    newest_time: Option<String>,
    newest_ref: Option<String>,
    oldest_time: Option<String>,
    oldest_ref: Option<String>,
}

impl ToString for Filter {
    fn to_string(&self) -> String {
        let mut v = Vec::new();

        v.push(format!(
            "order={}",
            self.order.as_deref().unwrap_or("ascending")
        ));
        v.push(format!("limit={}", self.limit.unwrap_or(10)));

        if let Some(user_id) = &self.user_id {
            v.push(format!("user_id={user_id}"));
        }

        for user in &self.users {
            v.push(format!("user={user}"));
        }

        for statuse in &self.statuses {
            v.push(format!("statuse={statuse}"));
        }

        for payment_type in &self.payment_types {
            v.push(format!("payment_type={payment_type}"));
        }

        for ty in &self.types {
            v.push(format!("type={ty}"));
        }

        if let Some(changes_since) = &self.changes_since {
            v.push(format!("changes_since={changes_since}"));
        }

        if let Some(newest_time) = &self.newest_time {
            v.push(format!("newest_time={newest_time}"));
        }

        if let Some(newest_ref) = &self.newest_ref {
            v.push(format!("newest_ref={newest_ref}"));
        }

        if let Some(oldest_time) = &self.oldest_time {
            v.push(format!("oldest_time={oldest_time}"));
        }

        if let Some(oldest_ref) = &self.oldest_ref {
            v.push(format!("oldest_ref={oldest_ref}"));
        }

        v.push("format=json".to_string());

        v.join("&")
    }
}
