//! The normalized data model the workbench renders.
//!
//! One struct per pane, plus a [`WorkbenchData`] that gathers them. The model
//! is intentionally flat and display-oriented; the extractors in
//! [`super::extract`] do the work of mapping varied artifact shapes onto it.

use serde::{Deserialize, Serialize};

/// One capability row (a tool, resource, or prompt).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CapItem {
    /// The capability name.
    pub name: String,
    /// Its description, possibly empty.
    pub description: String,
}

/// One JSON-RPC trace row.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TraceEntry {
    /// `request`, `response`, or a message direction.
    pub direction: String,
    /// The JSON-RPC method, when known.
    pub method: String,
    /// A short preview of the message body.
    pub summary: String,
}

/// One run-result row.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResultRow {
    /// Test name.
    pub name: String,
    /// Status label (`passed`, `failed`, `skipped`, ...).
    pub status: String,
}

/// The run-results summary pane.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResultsSummary {
    /// Total tests.
    pub total: usize,
    /// Passing tests.
    pub passed: usize,
    /// Failing tests.
    pub failed: usize,
    /// Skipped tests.
    pub skipped: usize,
    /// Per-test rows.
    pub rows: Vec<ResultRow>,
}

/// One security finding row.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SecItem {
    /// Finding id.
    pub id: String,
    /// Severity label.
    pub severity: String,
    /// Title or message.
    pub title: String,
}

/// Evidence pack metadata pane.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EvidenceMeta {
    /// Pack schema id.
    pub schema: String,
    /// Content digest.
    pub digest: String,
    /// When the pack was generated.
    pub generated_at: String,
    /// The section names the pack carries.
    pub sections: Vec<String>,
}

/// The gathered workbench data, one optional pane each.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct WorkbenchData {
    /// A label for the source (the live target, or the artifacts opened).
    pub source_label: String,
    /// Whether the data came from a live capture (vs saved artifacts).
    pub live: bool,
    /// Tools.
    pub tools: Vec<CapItem>,
    /// Resources.
    pub resources: Vec<CapItem>,
    /// Prompts.
    pub prompts: Vec<CapItem>,
    /// JSON-RPC trace rows.
    pub trace: Vec<TraceEntry>,
    /// Run results, when a report was opened.
    pub results: Option<ResultsSummary>,
    /// Security findings.
    pub security: Vec<SecItem>,
    /// Evidence metadata, when a pack was opened.
    pub evidence: Option<EvidenceMeta>,
}

impl WorkbenchData {
    /// Whether the workbench has any pane to show.
    pub fn is_empty(&self) -> bool {
        self.tools.is_empty()
            && self.resources.is_empty()
            && self.prompts.is_empty()
            && self.trace.is_empty()
            && self.results.is_none()
            && self.security.is_empty()
            && self.evidence.is_none()
    }
}
