#[derive(Debug, PartialEq)]
pub struct HMACAuthorizationHeader<'a> {
    pub sender: &'a str,
    pub recipient: &'a str,
    pub hmac: &'a str,
}

#[derive(Debug, PartialEq)]
pub enum HMACAuthorizationHeaderParseError {
    InvalidFormat,
    InvalidHMAC,
}

impl<'a> TryFrom<&'a str> for HMACAuthorizationHeader<'a> {
    type Error = HMACAuthorizationHeaderParseError;

    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        let Some((sender, rest)) = value.trim().split_once('/') else {
            return Err(HMACAuthorizationHeaderParseError::InvalidFormat);
        };

        let Some((recipient, hmac)) = rest.split_once(':') else {
            return Err(HMACAuthorizationHeaderParseError::InvalidFormat);
        };

        if hmac.len() != 40 || !hmac.chars().all(|c| c.is_ascii_hexdigit()) {
            return Err(HMACAuthorizationHeaderParseError::InvalidHMAC);
        }

        Ok(HMACAuthorizationHeader {
            sender,
            recipient,
            hmac,
        })
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_try_parse_valid_hmac() {
        let result = HMACAuthorizationHeader::try_from(
            "sender/recipient:5745fd9c0640945e8b744def34ebafff9e9f6846",
        );

        assert_eq!(
            result,
            Ok(HMACAuthorizationHeader {
                sender: "sender",
                recipient: "recipient",
                hmac: "5745fd9c0640945e8b744def34ebafff9e9f6846",
            })
        );
    }

    #[test]
    fn test_try_parse_invalid_format_no_forward_slash() {
        let result = HMACAuthorizationHeader::try_from(
            "sender|recipient:5745fd9c0640945e8b744def34ebafff9e9f6846",
        );

        assert_eq!(
            result,
            Err(HMACAuthorizationHeaderParseError::InvalidFormat)
        );
    }

    #[test]
    fn test_try_parse_invalid_format_no_colon() {
        let result = HMACAuthorizationHeader::try_from(
            "sender/recipient=5745fd9c0640945e8b744def34ebafff9e9f6846",
        );

        assert_eq!(
            result,
            Err(HMACAuthorizationHeaderParseError::InvalidFormat)
        );
    }

    #[test]
    fn test_try_parse_invalid_hmac_wrong_length() {
        let result = HMACAuthorizationHeader::try_from(
            "sender/recipient:5745fd9c0640945e8b744def34ebafff9e9f684612023023",
        );

        assert_eq!(result, Err(HMACAuthorizationHeaderParseError::InvalidHMAC));
    }

    #[test]
    fn test_try_parse_invalid_hmac_bad_characters() {
        let result = HMACAuthorizationHeader::try_from(
            "sender/recipient:5745fd9c0640945e8b744def34ebafff9e9f684!",
        );

        assert_eq!(result, Err(HMACAuthorizationHeaderParseError::InvalidHMAC));
    }
}
