use std::path::PathBuf;

use anyhow::Context;
use entertainarr_domain::media::entity::VideoStreamResponse;

#[derive(derive_more::From)]
pub enum TreeWalker {
    PCloud(entertainarr_adapter_filesystem_pcloud::PcloudWalkTree),
}

impl entertainarr_domain::media::prelude::TreeWalker for TreeWalker {
    async fn next(
        &mut self,
    ) -> anyhow::Result<Option<entertainarr_domain::media::entity::MediaFileInput>> {
        match self {
            Self::PCloud(inner) => inner.next().await,
        }
    }
}

impl super::FileSystemClient {
    fn traverse(&self, path: &str) -> anyhow::Result<TreeWalker> {
        match self {
            Self::PCloud(inner) => inner
                .traverse(path)
                .map(TreeWalker::PCloud)
                .context("unable to traverse pcloud directory"),
        }
    }

    async fn video_stream(&self, filepath: PathBuf) -> anyhow::Result<Option<VideoStreamResponse>> {
        match self {
            Self::PCloud(inner) => inner.video_stream(filepath).await,
        }
    }
}

impl crate::InnerClient {
    fn disks(&self) -> Vec<String> {
        self.disks.keys().cloned().collect()
    }
}

impl entertainarr_domain::media::prelude::MediaStore for crate::Client {
    type Walker = TreeWalker;

    fn disks(&self) -> Vec<String> {
        self.0.disks()
    }

    fn traverse(&self, name: &str, path: &str) -> anyhow::Result<Option<Self::Walker>> {
        self.0
            .disks
            .get(name)
            .map(|disk| disk.traverse(path))
            .transpose()
    }

    async fn video_stream(
        &self,
        disk: &str,
        path: std::path::PathBuf,
    ) -> anyhow::Result<Option<entertainarr_domain::media::entity::VideoStreamResponse>> {
        let Some(disk) = self.0.disks.get(disk) else {
            return Ok(None);
        };

        disk.video_stream(path).await
    }
}
