//! Konkreter Vertrag für die spätere native Erzeugung, ohne Phase-5-Dateiausgabe.
use crate::documents::{Destination, DocumentId, Project};
use anyhow::{ensure, Result};
use std::path::PathBuf;
use tb_vm::project_io::{has_extension, Manifest};

pub const UNAVAILABLE: &str = "Native Erzeugung folgt in Phase 6";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Artifact {
    Executable,
    Library,
}
impl Artifact {
    pub fn label(self) -> &'static str {
        match self {
            Self::Executable => "Natives Standalone-Executable",
            Self::Library => "Native Systembibliothek",
        }
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectStamp {
    pub path: Option<PathBuf>,
    pub manifest: Manifest,
    pub revisions: Vec<(DocumentId, u64)>,
}
impl ProjectStamp {
    pub fn capture(project: &Project) -> Self {
        Self {
            path: project.path().map(PathBuf::from),
            manifest: project.manifest().clone(),
            revisions: project
                .documents()
                .map(|(id, d)| (id, d.revision()))
                .collect(),
        }
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExportRequest {
    pub project: ProjectStamp,
    pub artifact: Artifact,
    pub system: String,
    pub architecture: String,
    pub path: PathBuf,
    pub overwrite: bool,
}
impl ExportRequest {
    pub fn validate(
        project: &Project,
        artifact: Artifact,
        system: &str,
        architecture: &str,
        destination: &Destination,
    ) -> Result<Self> {
        ensure!(
            ["linux", "macos", "windows"].contains(&system),
            "Unbekanntes Zielsystem"
        );
        ensure!(
            ["x86_64", "aarch64"].contains(&architecture),
            "Unbekannte Zielarchitektur"
        );
        ensure!(
            !has_extension(&destination.path, "tbc"),
            "TBC ist kein natives Exportartefakt"
        );
        let path = project.validate_export_target(destination)?;
        Ok(Self {
            project: ProjectStamp::capture(project),
            artifact,
            system: system.into(),
            architecture: architecture.into(),
            path,
            overwrite: destination.overwrite,
        })
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExportStatus {
    Ready,
    Running,
    Success,
    Failed(String),
    Cancelled,
}
impl ExportStatus {
    pub fn text(&self) -> String {
        match self {
            Self::Ready => "Geprüft".into(),
            Self::Running => "Erzeugung läuft".into(),
            Self::Success => "Erfolgreich erzeugt".into(),
            Self::Failed(e) => format!("Erzeugung fehlgeschlagen: {e}"),
            Self::Cancelled => "Erzeugung abgebrochen".into(),
        }
    }
}
