use super::Options;
use crate::storage::{Error, object_store::ObjectStore};
use async_trait::async_trait;
use std::path::{Path, PathBuf};
use tempfile::NamedTempFile;
use tokio::fs;
use url::Url;

pub struct LocalFileSystemObjectStore {
    #[allow(unused)]
    url: Url,
}

impl LocalFileSystemObjectStore {
    pub async fn new(url: &Url, _options: Options) -> Result<Self, Error> {
        Ok(Self { url: url.clone() })
    }
}

#[async_trait]
impl ObjectStore for LocalFileSystemObjectStore {
    async fn del(&self, key: &str) -> Result<(), Error> {
        let path = PathBuf::from(self.url.path()).join(key);
        if !path.exists() {
            return Err(Error::NotFound("No such file".to_string()));
        }
        tokio::fs::remove_file(path)
            .await
            .map_err(|e| Error::internal(e.to_string()))?;
        Ok(())
    }

    async fn get(&self, key: &str) -> Result<NamedTempFile, Error> {
        let path = PathBuf::from(self.url.path()).join(key);
        if !path.exists() {
            return Err(Error::NotFound("No such file".to_string()));
        }
        let file = NamedTempFile::new().map_err(|e| Error::internal(e.to_string()))?;
        fs::copy(path, file.path())
            .await
            .map_err(|e| Error::internal(e.to_string()))?;
        Ok(file)
    }

    async fn put(&self, key: &str, path: &Path) -> Result<(), Error> {
        let to_path = PathBuf::from(self.url.path()).join(key);
        tokio::fs::copy(path, &to_path)
            .await
            .map_err(|e| Error::internal(e.to_string()))?;
        Ok(())
    }
}
