//! Alias management for local Episteme operations.
//!
//! Handles auto-alias creation and manual alias management.

use stemedb_core::types::{AliasOrigin, ConceptAlias, ConceptPath};
use stemedb_storage::AliasStore;
use tracing::{debug, instrument};

use crate::AphoriaError;

use super::corpus::current_timestamp;
use super::local::LocalEpisteme;

impl LocalEpisteme {
    /// Create an alias from a code path to an authoritative path, if it doesn't already exist.
    ///
    /// This is used during conflict detection to persist the relationship between
    /// code concepts and their authoritative counterparts.
    #[instrument(skip(self), fields(code_path = %code_path, auth_path = %auth_path))]
    pub async fn create_alias_if_new(
        &self,
        code_path: &str,
        auth_path: &str,
        agent_id: [u8; 32],
        timestamp: u64,
    ) -> Result<(), AphoriaError> {
        // Check if alias already exists
        let existing = self.alias_store().get_canonical(code_path).await.map_err(|e| {
            AphoriaError::Storage(format!("Failed to get canonical alias for {code_path}: {e}"))
        })?;

        if existing.is_some() {
            debug!("Alias already exists, skipping");
            return Ok(());
        }

        // Parse paths
        let alias_path = ConceptPath::parse(code_path)
            .map_err(|e| AphoriaError::Storage(format!("Invalid code path: {}", e)))?;
        let canonical_path = ConceptPath::parse(auth_path)
            .map_err(|e| AphoriaError::Storage(format!("Invalid auth path: {}", e)))?;

        // Create and persist alias
        let alias = ConceptAlias::new(
            alias_path,
            canonical_path,
            agent_id,
            timestamp,
            AliasOrigin::AutoDetected,
        );

        self.alias_store().set_alias(&alias).await.map_err(|e| {
            AphoriaError::Storage(format!(
                "Failed to set alias from {code_path} to {auth_path}: {e}"
            ))
        })?;

        debug!("Created auto-detected alias");
        Ok(())
    }

    /// Fetch manual aliases for policy export.
    ///
    /// Returns all aliases stored in the local Episteme instance.
    /// These can be auto-detected aliases from conflict detection or
    /// manually created aliases.
    pub async fn fetch_manual_aliases(&self) -> Result<Vec<ConceptAlias>, AphoriaError> {
        let alias_tuples = self
            .alias_store()
            .list_all_aliases()
            .await
            .map_err(|e| AphoriaError::Storage(format!("Failed to list all aliases: {e}")))?;

        let timestamp = current_timestamp();
        let agent_id = self.agent_id();

        // Convert (alias_str, canonical_str) tuples to ConceptAlias structs
        let aliases = alias_tuples
            .into_iter()
            .filter_map(|(alias_str, canonical_str)| {
                let alias_path = ConceptPath::parse(&alias_str).ok()?;
                let canonical_path = ConceptPath::parse(&canonical_str).ok()?;
                Some(ConceptAlias::new(
                    alias_path,
                    canonical_path,
                    agent_id,
                    timestamp,
                    AliasOrigin::Manual, // Treat all exported aliases as manual
                ))
            })
            .collect();

        Ok(aliases)
    }
}
