use ipnet::IpNet;
use log::error;
use netlink_packet_route::{
    route::{RouteAddress, RouteAttribute, RouteMessage, RouteProtocol},
    AddressFamily,
};
use std::{
    fmt,
    net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum RouteError {
    #[error("Invalid gateway")]
    InvalidGateway,

    #[error("Invalid destination")]
    InvalidDestination,

    #[error("Invalid prefix length")]
    InvalidPrefixLength,

    #[error("Missing gateway")]
    MissingGateway,

    #[error("Missing destination")]
    MissingDestination,
}

pub struct Route {
    pub protocol: RouteProtocol,
    pub destination: IpNet,
    pub gateway: IpAddr,
}

impl fmt::Debug for Route {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} via {}", self.destination, self.gateway)
    }
}

impl Route {
    pub fn from_message(message: RouteMessage) -> Result<Self, RouteError> {
        let mut gateway = None;
        let mut destination = None;

        for nla in message.attributes.iter() {
            if let RouteAttribute::Gateway(ip) = nla {
                gateway = match ip {
                    RouteAddress::Inet(ip) => Some(IpAddr::V4(*ip)),
                    RouteAddress::Inet6(ip) => Some(IpAddr::V6(*ip)),
                    _ => return Err(RouteError::InvalidGateway),
                };
            }

            if let RouteAttribute::Destination(ref ip) = nla {
                destination = match ip {
                    RouteAddress::Inet(ip) => Some(
                        IpNet::new(IpAddr::V4(*ip), message.header.destination_prefix_length)
                            .map_err(|_| RouteError::InvalidPrefixLength)?,
                    ),
                    RouteAddress::Inet6(ip) => Some(
                        IpNet::new(IpAddr::V6(*ip), message.header.destination_prefix_length)
                            .map_err(|_| RouteError::InvalidPrefixLength)?,
                    ),
                    _ => return Err(RouteError::InvalidDestination),
                };
            }
        }

        let gateway = match gateway {
            Some(gateway) => gateway,
            None => return Err(RouteError::MissingGateway),
        };

        let destination = match destination {
            Some(destination) => destination,
            None => match message.header.address_family {
                AddressFamily::Inet => IpNet::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)
                    .map_err(|_| RouteError::InvalidPrefixLength)?,
                AddressFamily::Inet6 => IpNet::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)
                    .map_err(|_| RouteError::InvalidPrefixLength)?,
                _ => return Err(RouteError::InvalidDestination),
            },
        };

        Ok(Route {
            protocol: message.header.protocol,
            destination,
            gateway,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use netlink_packet_route::AddressFamily;
    use std::net::Ipv4Addr;

    #[tokio::test]
    async fn test_default_ipv4_route() {
        let mut message = RouteMessage::default();

        message.header.address_family = AddressFamily::Inet;
        message.header.destination_prefix_length = 0;
        message.header.protocol = RouteProtocol::Static;
        message
            .attributes
            .push(RouteAttribute::Gateway(RouteAddress::Inet(Ipv4Addr::new(
                192, 168, 1, 1,
            ))));

        let route = Route::from_message(message).unwrap();

        assert_eq!(route.protocol, RouteProtocol::Static);
        assert_eq!(
            route.destination,
            IpNet::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0).unwrap()
        );
        assert_eq!(route.gateway, IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)));
    }

    #[tokio::test]
    async fn test_default_ipv6_route() {
        let mut message = RouteMessage::default();

        message.header.address_family = AddressFamily::Inet6;
        message.header.destination_prefix_length = 0;
        message.header.protocol = RouteProtocol::Static;
        message
            .attributes
            .push(RouteAttribute::Gateway(RouteAddress::Inet6(Ipv6Addr::new(
                0, 0, 0, 0, 0, 0, 0, 1,
            ))));

        let route = Route::from_message(message).unwrap();

        assert_eq!(route.protocol, RouteProtocol::Static);
        assert_eq!(
            route.destination,
            IpNet::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0).unwrap()
        );
        assert_eq!(
            route.gateway,
            IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
        );
    }
}
