//! Shared types and utilities for Syntaxis Dashboard
//!
//! This crate contains shared data structures used by both the frontend (dashboard-client)
//! and backend (syntaxis-api) to ensure type consistency across the application.

#![forbid(unsafe_code)]
#![warn(missing_docs)]

use serde::{Deserialize, Serialize};

/// Represents a project event in the lifecycle system
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct ProjectEvent {
    /// Type of event (e.g., "status_change", "milestone_reached")
    pub event_type: String,
    /// Unique identifier for the project
    pub project_id: String,
    /// ISO 8601 timestamp of when the event occurred
    pub timestamp: String,
    /// Optional message describing the event
    pub message: Option<String>,
    /// Optional metadata as JSON string
    pub metadata: Option<String>,
}

/// Application theme preference
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum Theme {
    /// Light theme
    #[default]
    Light,
    /// Dark theme
    Dark,
}

impl Theme {
    /// Returns the theme as a string for CSS class names
    pub fn as_str(&self) -> &'static str {
        match self {
            Theme::Light => "light",
            Theme::Dark => "dark",
        }
    }
}

/// Dashboard configuration shared across components
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DashboardConfig {
    /// API base URL
    pub api_base_url: String,
    /// WebSocket endpoint URL
    pub ws_url: Option<String>,
    /// Enable debug mode
    pub debug: bool,
}

impl Default for DashboardConfig {
    fn default() -> Self {
        Self {
            api_base_url: "http://localhost:8080".to_string(),
            ws_url: Some("ws://localhost:8080/ws".to_string()),
            debug: false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_project_event_serialization() {
        let event = ProjectEvent {
            event_type: "test".to_string(),
            project_id: "proj-123".to_string(),
            timestamp: "2025-11-14T00:00:00Z".to_string(),
            message: Some("Test message".to_string()),
            metadata: None,
        };

        let json = serde_json::to_string(&event).expect("Failed to serialize");
        let deserialized: ProjectEvent =
            serde_json::from_str(&json).expect("Failed to deserialize");

        assert_eq!(event, deserialized);
    }

    #[test]
    fn test_theme_default() {
        assert_eq!(Theme::default(), Theme::Light);
    }

    #[test]
    fn test_theme_as_str() {
        assert_eq!(Theme::Light.as_str(), "light");
        assert_eq!(Theme::Dark.as_str(), "dark");
    }

    #[test]
    fn test_dashboard_config_default() {
        let config = DashboardConfig::default();
        assert_eq!(config.api_base_url, "http://localhost:8080");
        assert_eq!(config.ws_url, Some("ws://localhost:8080/ws".to_string()));
        assert!(!config.debug);
    }

    #[test]
    fn test_dashboard_config_serialization() {
        let config = DashboardConfig::default();
        let json = serde_json::to_string(&config).expect("Failed to serialize");
        let deserialized: DashboardConfig =
            serde_json::from_str(&json).expect("Failed to deserialize");

        assert_eq!(config.api_base_url, deserialized.api_base_url);
    }
}
