use std::path::PathBuf;

use crate::{
    cuddle_file::{CuddleDatabase, CuddleFile},
    rust_service::extensions::AptExt,
};

use super::{
    extensions::{AssetsExt, CargoCleanExt, SqlxExt},
    RustService,
};

#[derive(Default)]
pub struct CuddleFileAction {}

impl CuddleFileAction {
    pub fn new() -> Self {
        Self {}
    }
}

pub trait CuddleFileExt {
    fn with_cuddle_file(&mut self, cuddle_file: &CuddleFile) -> &mut Self;
}

impl CuddleFileExt for RustService {
    fn with_cuddle_file(&mut self, cuddle_file: &CuddleFile) -> &mut Self {
        let mut s = self
            .with_bin_name(&cuddle_file.vars.service)
            .with_deployment(false);

        tracing::trace!("with cuddle file: {:+?}", &cuddle_file);

        if let Some(components) = &cuddle_file.components {
            s = if let Some(database) = &components.database {
                match database {
                    CuddleDatabase::Enabled(true) => s.with_sqlx_migrations(
                        PathBuf::from("crates")
                            .join(&cuddle_file.vars.service)
                            .join("migrations/crdb"),
                    ),
                    CuddleDatabase::Values { migrations } => s.with_sqlx_migrations(migrations),
                    CuddleDatabase::Enabled(false) | CuddleDatabase::Default {} => s,
                }
            } else {
                s
            };

            if let Some(assets) = &components.assets {
                if let Some(true) = assets.clean {
                    s = s.with_cargo_clean()
                }

                if let Some(volumes) = &assets.volumes {
                    let mappings = volumes.iter().cloned().map(|val| (val.from, val.to));

                    s = s.with_assets(mappings);
                }
            }

            if let Some(packages) = &components.packages {
                s = s
                    .with_apt(
                        packages
                            .debian
                            .dev
                            .iter()
                            .map(|r| r.as_str())
                            .collect::<Vec<_>>()
                            .as_slice(),
                    )
                    .with_apt_release(
                        packages
                            .debian
                            .release
                            .iter()
                            .map(|r| r.as_str())
                            .collect::<Vec<_>>()
                            .as_slice(),
                    );
            }
        }

        s
    }
}
