use crate::models::List;

use super::Source;
use async_trait::async_trait;

#[derive(Debug)]
pub struct FileSource {
    path: String,
    lifetime: u64,
}

impl FileSource {
    pub fn new(path: String, lifetime: u64) -> Self {
        Self { path, lifetime }
    }
}

#[async_trait]
impl Source for FileSource {
    type Error = Error;

    async fn fetch(&self) -> Result<List, Self::Error> {
        let raw = tokio::fs::read(&self.path).await.map_err(|err| {
            tracing::error!("failed to read list from file: {err}");
            Error::File
        })?;

        serde_json::from_slice(&raw).map_err(|err| {
            tracing::error!("failed to deserialize list: {err}");
            Error::Deserialize
        })
    }

    fn lifetime(&self) -> u64 {
        self.lifetime
    }
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("failed to read file")]
    File,

    #[error("could not deserialize list")]
    Deserialize,
}
