//! `Adapter` contract and linter-command type.

use std::path::Path;

use aqc_file_engine_core::Provenance;

use crate::adapter_requirement::AdapterRequirement;
use crate::engine_output::EngineRequirementOutput;

/// Adapter lowering failed for one policy requirement.
#[expect(
    clippy::module_name_repetitions,
    reason = "`AdapterError` is the public error type for the Adapter trait."
)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AdapterError {
    WrongRequirementType {
        adapter_id: &'static str,
        expected: &'static str,
    },
}

/// A linter's command line, as data.
#[derive(Debug, Clone)]
pub struct LinterCommand {
    /// Program name.
    pub program: String,
    /// Program arguments.
    pub args: Vec<String>,
}

/// A linter adapter lowers one policy requirement into engine requirements.
pub trait Adapter {
    /// Stable adapter id.
    fn id(&self) -> &'static str;
    /// Lower one policy requirement. The same provenance is retained beside
    /// every engine requirement the adapter emits.
    ///
    /// # Errors
    ///
    /// Returns `AdapterError` when the requirement does not match the adapter's
    /// concrete requirement type.
    fn lower(
        &self,
        provenance: Provenance,
        requirement: Box<dyn AdapterRequirement>,
    ) -> Result<EngineRequirementOutput, AdapterError>;
    /// This linter's command as data for wiring files, or `None`.
    fn lint_command(&self, workspace_root: &Path) -> Option<LinterCommand>;
}
