use crate::errors::*;
use chrono::{DateTime, Duration, NaiveDateTime, Utc};
use forensic_adb::Device;

const DATE_COMMAND: &str = "date -u '+%Y-%m-%d %T %N'";

pub async fn determine(device: &Device) -> Result<(DateTime<Utc>, DateTime<Utc>, Duration)> {
    let output = device
        .execute_host_exec_out_command(DATE_COMMAND)
        .await
        .with_context(|| anyhow!("Failed to run date command: {:?}", DATE_COMMAND))?;
    let local_time = Utc::now();
    let output = String::from_utf8_lossy(&output);
    let remote_time = parse(output.trim()).context("Failed to parse remote time")?;
    let drift = remote_time.signed_duration_since(local_time);
    Ok((local_time, remote_time, drift))
}

fn parse(s: &str) -> Result<DateTime<Utc>> {
    let dt = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %T %f")?;
    Ok(DateTime::<Utc>::from_naive_utc_and_offset(dt, Utc))
}

#[cfg(test)]
mod tests {
    use super::*;
    use chrono::{TimeZone, Timelike};

    #[test]
    fn test_parse_date() {
        let dt = parse("2021-10-21 22:37:56 716729236").unwrap();
        assert_eq!(
            dt,
            Utc.with_ymd_and_hms(2021, 10, 21, 22, 37, 56)
                .unwrap()
                .with_nanosecond(716729236)
                .unwrap()
        );
    }
}
