//! DTOs for ConceptPath and Alias operations.
//!
//! Supports hierarchical concept paths and cross-scheme alias resolution.

use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

/// Request to create a concept alias.
///
/// Creates a bidirectional mapping between an alias path and its canonical form.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateAliasRequest {
    /// The alias path (e.g., `code://rust/auth/jwt/aud`)
    pub alias_path: String,

    /// The canonical path (e.g., `rfc://7519/jwt/audience_validation`)
    pub canonical_path: String,

    /// Origin of the alias (Manual, Suggested, Merged). Defaults to Manual.
    pub origin: Option<AliasOriginDto>,

    /// Hex-encoded Ed25519 public key of the agent creating the alias (32 bytes).
    pub agent_id: String,
}

/// Response after creating an alias.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AliasResponse {
    /// The alias path
    pub alias_path: String,

    /// The canonical path
    pub canonical_path: String,

    /// When the alias was created (Unix timestamp)
    pub created_at: u64,

    /// Origin of the alias
    pub origin: AliasOriginDto,
}

/// Origin of an alias.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema, Default)]
#[serde(rename_all = "PascalCase")]
pub enum AliasOriginDto {
    /// Manually created by an agent
    #[default]
    Manual,

    /// Suggested by the system based on similarity
    Suggested,

    /// Created during entity merge operation
    Merged,
}

/// Request to delete an alias.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DeleteAliasRequest {
    /// The alias path to delete
    pub alias_path: String,
}

/// Response after deleting an alias.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DeleteAliasResponse {
    /// Whether the alias was deleted (false if it didn't exist)
    pub deleted: bool,

    /// The alias path that was (attempted to be) deleted
    pub alias_path: String,
}

/// Query parameters for alias resolution.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ResolveAliasParams {
    /// The path to resolve (can be an alias or canonical)
    pub path: String,

    /// If true, resolve transitively to find all related paths.
    /// If false (default), only return the direct canonical.
    #[serde(default)]
    pub transitive: bool,
}

/// Response from alias resolution.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ResolveAliasResponse {
    /// The original path queried
    pub input_path: String,

    /// All resolved paths (includes input, canonical, and transitive aliases if requested)
    pub resolved_paths: Vec<String>,
}

/// List all aliases query parameters.
#[derive(Debug, Clone, Serialize, Deserialize, Default, ToSchema)]
pub struct ListAliasesParams {
    /// Filter by canonical path (returns aliases pointing to this canonical)
    pub canonical_path: Option<String>,

    /// Maximum number of aliases to return
    #[serde(default = "default_limit")]
    pub limit: usize,
}

fn default_limit() -> usize {
    100
}

/// Response listing aliases.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ListAliasesResponse {
    /// List of alias mappings (alias_path → canonical_path)
    pub aliases: Vec<AliasMapping>,

    /// Total number of aliases (may be more than returned if limited)
    pub total: usize,
}

/// A single alias mapping.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AliasMapping {
    /// The alias path
    pub alias_path: String,

    /// The canonical path
    pub canonical_path: String,
}

/// Alias suggestion response.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AliasSuggestion {
    /// The suggested canonical path
    pub suggested_canonical: String,

    /// Reason for the suggestion (e.g., "Same leaf 'aud' across schemes")
    pub reason: String,
}

/// Response listing alias suggestions.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct SuggestAliasesResponse {
    /// The input path that suggestions are for
    pub input_path: String,

    /// List of suggestions
    pub suggestions: Vec<AliasSuggestion>,
}

/// Parsed ConceptPath information.
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ConceptPathInfo {
    /// The full wire format path
    pub path: String,

    /// The scheme (e.g., "code", "rfc", "fda")
    pub scheme: String,

    /// The path segments
    pub segments: Vec<String>,

    /// The leaf (last segment)
    pub leaf: String,

    /// The inferred source class based on scheme
    pub inferred_source_class: String,
}
