use std::sync::Arc;

use crate::forest_client::GrpcForestClient;
use crate::templates::TemplateEngine;
use forage_core::auth::ForestAuth;
use forage_core::integrations::IntegrationStore;
use forage_core::platform::ForestPlatform;
use forage_core::session::SessionStore;

/// Slack OAuth credentials for the "Add to Slack" flow.
#[derive(Clone)]
pub struct SlackConfig {
    pub client_id: String,
    pub client_secret: String,
    pub redirect_host: String,
}

#[derive(Clone)]
pub struct AppState {
    pub templates: TemplateEngine,
    pub forest_client: Arc<dyn ForestAuth>,
    pub platform_client: Arc<dyn ForestPlatform>,
    pub sessions: Arc<dyn SessionStore>,
    pub grpc_client: Option<Arc<GrpcForestClient>>,
    pub integration_store: Option<Arc<dyn IntegrationStore>>,
    pub slack_config: Option<SlackConfig>,
}

impl AppState {
    pub fn new(
        templates: TemplateEngine,
        forest_client: Arc<dyn ForestAuth>,
        platform_client: Arc<dyn ForestPlatform>,
        sessions: Arc<dyn SessionStore>,
    ) -> Self {
        Self {
            templates,
            forest_client,
            platform_client,
            sessions,
            grpc_client: None,
            integration_store: None,
            slack_config: None,
        }
    }

    pub fn with_grpc_client(mut self, client: Arc<GrpcForestClient>) -> Self {
        self.grpc_client = Some(client);
        self
    }

    pub fn with_integration_store(mut self, store: Arc<dyn IntegrationStore>) -> Self {
        self.integration_store = Some(store);
        self
    }

    pub fn with_slack_config(mut self, config: SlackConfig) -> Self {
        self.slack_config = Some(config);
        self
    }
}
