//! Narrow conflict-checking manifest used at session init.
//! The full registry manifest lives in `plugin_manifest.rs`; this one
//! is intentionally minimal because conflict checking only needs the
//! trait/phase/settings surface, not the marketplace metadata.

use crate::trait_data::TraitSet;
use crate::phases::PhaseDescriptor;
use crate::settings::SettingsSchema;
use crate::types::PhaseId;

#[derive(Debug, Clone)]
pub struct ConflictManifest {
    pub id: String,
    pub version: (u32, u32, u32),
    pub provides_traits: TraitSet,
    pub requires_traits: TraitSet,
    pub optional_traits: TraitSet,
    pub declares_phases: Vec<PhaseDescriptor>,
    pub model_settings: SettingsSchema,
}

impl ConflictManifest {
    pub fn new(id: impl Into<String>) -> Self {
        Self {
            id: id.into(),
            version: (0, 1, 0),
            provides_traits: TraitSet::empty(),
            requires_traits: TraitSet::empty(),
            optional_traits: TraitSet::empty(),
            declares_phases: vec![],
            model_settings: SettingsSchema::empty(),
        }
    }
}

#[derive(Debug, Clone)]
pub enum ConflictError {
    MissingRequiredTrait { plugin: String, missing: TraitSet },
    PhaseIdCollision { phase_id: PhaseId, plugins: Vec<String> },
    UnknownPlugin { plugin_id: String },
}

/// One declarative entry in a plugin's `templates_index()`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TemplateIndexEntry {
    pub template_id: String,
    pub system_id:   String,
}

impl TemplateIndexEntry {
    pub fn new(template_id: impl Into<String>, system_id: impl Into<String>) -> Self {
        Self {
            template_id: template_id.into(),
            system_id:   system_id.into(),
        }
    }
}
