//! Documenter agent integration with doc-lifecycle

use std::sync::Arc;

use crate::config::PluginConfig;
use crate::plugin::DocLifecyclePlugin;
use crate::Result;

/// Documenter agent integration
#[derive(Debug)]
pub struct DocumenterIntegration {
    plugin: DocLifecyclePlugin,
    config: PluginConfig,
    nats: Option<Arc<async_nats::Client>>,
}

impl DocumenterIntegration {
    /// Create a new documenter integration
    pub fn new(config: PluginConfig) -> Result<Self> {
        let plugin = DocLifecyclePlugin::new(config.clone())?;

        Ok(Self {
            plugin,
            config,
            nats: None,
        })
    }

    /// Attach a NATS client for publishing doc-updated events.
    pub fn with_nats(mut self, client: Arc<async_nats::Client>) -> Self {
        self.nats = Some(client);
        self
    }

    /// Handle task completion event
    pub async fn on_task_completed(&mut self, task_id: &str) -> Result<()> {
        tracing::info!(
            "Documenter: Processing task completion for task {}",
            task_id
        );

        self.plugin.process_task_docs(task_id).await?;
        self.update_root_files(task_id).await?;
        self.publish_docs_updated_event(task_id).await?;

        Ok(())
    }

    async fn update_root_files(&self, task_id: &str) -> Result<()> {
        use std::io::Write;

        let changes_path = self.config.docs_root.join("CHANGES.md");
        let timestamp = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%SZ");
        let line = format!("- {timestamp} task `{task_id}` docs processed\n");

        let mut file = std::fs::OpenOptions::new()
            .create(true)
            .append(true)
            .open(&changes_path)?;

        file.write_all(line.as_bytes())?;
        tracing::info!(
            task_id = %task_id,
            path = %changes_path.display(),
            "CHANGES.md updated"
        );
        Ok(())
    }

    async fn publish_docs_updated_event(&self, task_id: &str) -> Result<()> {
        let Some(nats) = &self.nats else {
            tracing::debug!(task_id = %task_id, "NATS not configured; skipping docs-updated event");
            return Ok(());
        };

        let payload = serde_json::json!({
            "event": "docs.updated",
            "task_id": task_id,
            "timestamp": chrono::Utc::now().to_rfc3339(),
        });

        let bytes = serde_json::to_vec(&payload)
            .map_err(|e| crate::Error::NatsError(format!("Serialization failed: {e}")))?;

        nats.publish(self.config.nats_subject.clone(), bytes.into())
            .await
            .map_err(|e| crate::Error::NatsError(format!("Publish failed: {e}")))?;

        tracing::info!(
            task_id = %task_id,
            subject = %self.config.nats_subject,
            "docs-updated event published"
        );
        Ok(())
    }

    /// Get current configuration
    #[must_use]
    pub fn config(&self) -> &PluginConfig {
        &self.config
    }
}
