//! Core types for syntaxis management

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Project metadata
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectMetadata {
    /// Project name
    pub name: String,
    /// Project version
    pub version: String,
    /// Project description
    pub description: String,
    /// Authors
    pub authors: Vec<String>,
    /// Repository URL
    pub repository: Option<String>,
    /// License
    pub license: String,
    /// Keywords
    pub keywords: Vec<String>,
    /// Categories
    pub categories: Vec<String>,
    /// Creation timestamp
    pub created: DateTime<Utc>,
    /// Last updated timestamp
    pub last_updated: DateTime<Utc>,
}

impl Default for ProjectMetadata {
    fn default() -> Self {
        let now = Utc::now();
        Self {
            name: String::new(),
            version: "0.1.0".to_string(),
            description: String::new(),
            authors: vec![],
            repository: None,
            license: "MIT".to_string(),
            keywords: vec![],
            categories: vec![],
            created: now,
            last_updated: now,
        }
    }
}

/// Project type
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ProjectType {
    /// Rust web application (Leptos + Axum)
    RustWeb,
    /// Rust CLI application
    RustCli,
    /// Rust embedded application
    RustEmbedded,
    /// Multi-language project
    MultiLang,
    /// NuShell script
    NuShellScript,
    /// Custom project type
    Custom(String),
}

impl std::fmt::Display for ProjectType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::RustWeb => write!(f, "rust-web"),
            Self::RustCli => write!(f, "rust-cli"),
            Self::RustEmbedded => write!(f, "rust-embedded"),
            Self::MultiLang => write!(f, "multi-lang"),
            Self::NuShellScript => write!(f, "nushell-script"),
            Self::Custom(s) => write!(f, "{}", s),
        }
    }
}

/// Project mode
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ProjectMode {
    /// Standalone mode
    Standalone,
    /// Vapora mode (multi-agent)
    Vapora,
    /// Provisioning mode (Kubernetes)
    Provisioning,
}

impl std::fmt::Display for ProjectMode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Standalone => write!(f, "standalone"),
            Self::Vapora => write!(f, "vapora"),
            Self::Provisioning => write!(f, "provisioning"),
        }
    }
}

/// Template variables
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TemplateVariables {
    /// Variables map
    pub variables: HashMap<String, String>,
}

impl TemplateVariables {
    /// Create a new template variables container
    pub fn new() -> Self {
        Self::default()
    }

    /// Insert a variable
    pub fn insert(&mut self, key: impl Into<String>, value: impl Into<String>) {
        self.variables.insert(key.into(), value.into());
    }

    /// Get a variable
    pub fn get(&self, key: &str) -> Option<&str> {
        self.variables.get(key).map(|s| s.as_str())
    }

    /// Check if variable exists
    pub fn contains_key(&self, key: &str) -> bool {
        self.variables.contains_key(key)
    }
}

/// Tool mode
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum ToolMode {
    /// Interactive mode (prompts user)
    Interactive,
    /// Automatic mode (uses defaults/config)
    Automatic,
    /// Manual mode (user-driven)
    Manual,
}

impl std::fmt::Display for ToolMode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Interactive => write!(f, "interactive"),
            Self::Automatic => write!(f, "automatic"),
            Self::Manual => write!(f, "manual"),
        }
    }
}

/// Publication target type
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum PublicationTargetType {
    /// Rustelo framework
    Rustelo,
    /// Website (CV, portfolio, etc)
    Website,
    /// Crates.io registry
    CratesIo,
    /// Docker registry
    Docker,
    /// Custom target
    Custom(String),
}

impl std::fmt::Display for PublicationTargetType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Rustelo => write!(f, "rustelo"),
            Self::Website => write!(f, "website"),
            Self::CratesIo => write!(f, "crates_io"),
            Self::Docker => write!(f, "docker"),
            Self::Custom(s) => write!(f, "{}", s),
        }
    }
}

/// Website type
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum WebsiteType {
    /// CV/resume website
    Cv,
    /// Portfolio website
    Portfolio,
    /// Blog
    Blog,
    /// Documentation
    Docs,
    /// Custom
    Custom(String),
}

impl std::fmt::Display for WebsiteType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Cv => write!(f, "cv"),
            Self::Portfolio => write!(f, "portfolio"),
            Self::Blog => write!(f, "blog"),
            Self::Docs => write!(f, "docs"),
            Self::Custom(s) => write!(f, "{}", s),
        }
    }
}

/// Deployment method for websites
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DeploymentMethod {
    /// Docker deployment
    Docker,
    /// Kubernetes deployment
    Kubernetes,
    /// Static hosting (GitHub Pages, etc)
    Static,
    /// Custom deployment
    Custom(String),
}

impl std::fmt::Display for DeploymentMethod {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Docker => write!(f, "docker"),
            Self::Kubernetes => write!(f, "kubernetes"),
            Self::Static => write!(f, "static"),
            Self::Custom(s) => write!(f, "{}", s),
        }
    }
}
