use async_trait::async_trait;
use log::info;

use crate::{
    executors::ExecutorError,
    topology::{HttpServer, IpAddress, Url},
};

use super::OPNSenseFirewall;

#[async_trait]
impl HttpServer for OPNSenseFirewall {
    async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError> {
        let http_root_path = "/usr/local/http";

        let config = self.opnsense_config.read().await;
        info!("Uploading files from url {url} to {http_root_path}");
        match url {
            Url::LocalFolder(path) => {
                config
                    .upload_files(path, http_root_path)
                    .await
                    .map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;
            }
            Url::Url(_url) => todo!(),
        }
        Ok(())
    }

    fn get_ip(&self) -> IpAddress {
        todo!();
    }

    async fn commit_config(&self) -> Result<(), ExecutorError> {
        OPNSenseFirewall::commit_config(self).await
    }

    async fn reload_restart(&self) -> Result<(), ExecutorError> {
        self.opnsense_config
            .write()
            .await
            .caddy()
            .reload_restart()
            .await
            .map_err(|e| ExecutorError::UnexpectedError(e.to_string()))
    }

    async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
        let mut config = self.opnsense_config.write().await;
        let caddy = config.caddy();
        if let None = caddy.get_full_config() {
            info!("Http config not available in opnsense config, installing package");
            config.install_package("os-caddy").await.map_err(|e| {
                ExecutorError::UnexpectedError(format!(
                    "Executor failed when trying to install os-caddy package with error {e:?}"
                ))
            })?;
        } else {
            info!("Http config available in opnsense config, assuming it is already installed");
        }
        info!("Adding custom caddy config files");
        config
            .upload_files(
                "../../../watchguard/caddy_config",
                "/usr/local/etc/caddy/caddy.d/",
            )
            .await
            .map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;

        info!("Enabling http server");
        config.caddy().enable(true);

        Ok(())
    }
}
