use anyhow::Result;
use newtype::NewType;
use serde::Serialize;
use std::collections::HashMap;

#[derive(Serialize, NewType)]
pub struct HttpApiReqHeader(HashMap<String, String>);

impl HttpApiReqHeader {
    pub fn from_json_str(json_str: &str) -> Result<Self> {
        let header: _ = serde_json::from_str(json_str)?;
        Ok(Self(header))
    }
}
#[derive(Serialize)]
pub struct HttpApiReq {
    header: HttpApiReqHeader,
    body: serde_json::Value,
}

impl HttpApiReq {
    pub fn new(header_str: &str, body: &str) -> Result<Self> {
        let header = HttpApiReqHeader::from_json_str(header_str)?;
        let body: serde_json::Value = serde_json::from_str(body)?;
        Ok(Self { header, body })
    }
    pub fn header(&self) -> &HttpApiReqHeader {
        &self.header
    }
    pub fn body_str(&self) -> String {
        self.body.to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_case_http_req() {
        let req = HttpApiReq::new(r#"{"hello":"world"}"#, r#"{"foo":"bar"}"#).unwrap();
        let json_str = serde_json::to_string(&req).unwrap();
        assert_eq!(json_str, r#"{"header":{"hello":"world"},"body":{"foo":"bar"}}"#);
        assert_eq!(req.body_str(), r#"{"foo":"bar"}"#);
    }
}
