use async_graphql::{EmptySubscription, Schema};
use std::sync::Arc;

use super::mutations::MutationRoot;
use super::queries::QueryRoot;
use crate::db::Database;
use crate::services::email_templates::EmailTemplateRegistry;
use crate::services::gmail::GmailService;
use crate::services::google_calendar::GoogleCalendarService;
use crate::services::job_queue::JobQueue;
use crate::services::s3::S3Service;
use crate::services::wave::WaveService;

pub type NexusSchema = Schema<QueryRoot, MutationRoot, EmptySubscription>;

/// Options for building the schema with external services
pub struct SchemaOptions {
    pub db: Database,
    pub calendar_service: Option<Arc<GoogleCalendarService>>,
    pub gmail_service: Option<Arc<GmailService>>,
    pub wave_service: Option<Arc<WaveService>>,
    pub s3_service: Option<Arc<S3Service>>,
    pub job_queue: Option<JobQueue>,
}

pub fn build_schema(options: SchemaOptions) -> NexusSchema {
    let mut builder = Schema::build(QueryRoot::default(), MutationRoot::default(), EmptySubscription)
        .data(options.db)
        .data(EmailTemplateRegistry::new());

    // Add optional services if they're configured
    if let Some(calendar) = options.calendar_service {
        builder = builder.data(calendar);
    }

    if let Some(gmail) = options.gmail_service {
        builder = builder.data(gmail);
    }

    if let Some(wave) = options.wave_service {
        builder = builder.data(wave);
    }

    if let Some(s3) = options.s3_service {
        builder = builder.data(s3);
    }

    if let Some(job_queue) = options.job_queue {
        builder = builder.data(job_queue);
    }

    builder.finish()
}
