//! Package service types
//!
//! Data types for package creation and manifest generation.

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

/// Supported target architectures
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum TargetArch {
    X8664UnknownLinuxGnu,
    Aarch64UnknownLinuxGnu,
    ArmV7UnknownLinuxGnueabihf,
    X8664AppleDarwin,
    Aarch64AppleDarwin,
}

impl FromStr for TargetArch {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "x86_64-unknown-linux-gnu" | "x86_64" => Ok(TargetArch::X8664UnknownLinuxGnu),
            "aarch64-unknown-linux-gnu" | "aarch64" | "arm64" => Ok(TargetArch::Aarch64UnknownLinuxGnu),
            "armv7-unknown-linux-gnueabihf" | "armv7" | "armhf" => Ok(TargetArch::ArmV7UnknownLinuxGnueabihf),
            "x86_64-apple-darwin" => Ok(TargetArch::X8664AppleDarwin),
            "aarch64-apple-darwin" => Ok(TargetArch::Aarch64AppleDarwin),
            _ => Err(format!("Invalid target architecture: {}", s)),
        }
    }
}

impl TargetArch {
    pub fn as_str(&self) -> &str {
        match self {
            TargetArch::X8664UnknownLinuxGnu => "x86_64-unknown-linux-gnu",
            TargetArch::Aarch64UnknownLinuxGnu => "aarch64-unknown-linux-gnu",
            TargetArch::ArmV7UnknownLinuxGnueabihf => "armv7-unknown-linux-gnueabihf",
            TargetArch::X8664AppleDarwin => "x86_64-apple-darwin",
            TargetArch::Aarch64AppleDarwin => "aarch64-apple-darwin",
        }
    }

    pub fn display_name(&self) -> &str {
        match self {
            TargetArch::X8664UnknownLinuxGnu => "x86_64 (Linux)",
            TargetArch::Aarch64UnknownLinuxGnu => "ARM64 (Linux)",
            TargetArch::ArmV7UnknownLinuxGnueabihf => "ARMv7 (Linux)",
            TargetArch::X8664AppleDarwin => "x86_64 (macOS)",
            TargetArch::Aarch64AppleDarwin => "ARM64 (macOS)",
        }
    }

    /// Get default target for current platform
    pub fn default_for_platform() -> Self {
        #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
        return TargetArch::X8664UnknownLinuxGnu;

        #[cfg(all(target_arch = "aarch64", target_os = "linux"))]
        return TargetArch::Aarch64UnknownLinuxGnu;

        #[cfg(all(target_arch = "x86_64", target_os = "macos"))]
        return TargetArch::X8664AppleDarwin;

        #[cfg(all(target_arch = "aarch64", target_os = "macos"))]
        return TargetArch::Aarch64AppleDarwin;

        #[cfg(not(any(
            all(target_arch = "x86_64", target_os = "linux"),
            all(target_arch = "aarch64", target_os = "linux"),
            all(target_arch = "x86_64", target_os = "macos"),
            all(target_arch = "aarch64", target_os = "macos")
        )))]
        return TargetArch::X8664UnknownLinuxGnu;
    }
}

/// Package manifest containing metadata about the package
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PackageManifest {
    pub format_version: String,
    pub name: String,
    pub version: String,
    pub build_timestamp: DateTime<Utc>,
    pub target_arch: TargetArch,
    pub binaries: Vec<BinaryInfo>,
    pub configs: Vec<ConfigInfo>,
    pub assets: Vec<AssetInfo>,
    pub dependencies: HashMap<String, String>,
    pub metadata: HashMap<String, serde_json::Value>,
    pub build_profile: String,
    pub git_commit: Option<String>,
    pub environment: Option<String>,
}

impl PackageManifest {
    pub const FORMAT_VERSION: &'static str = "1.0.0";
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BinaryInfo {
    pub name: String,
    pub path: String,
    pub size_bytes: u64,
    pub checksum: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConfigInfo {
    pub name: String,
    pub path: String,
    pub config_type: String,
    pub checksum: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetInfo {
    pub name: String,
    pub path: String,
    pub asset_type: String,
    pub size_bytes: u64,
    pub checksum: String,
}

/// Package configuration
#[derive(Debug, Clone)]
pub struct PackageConfig {
    pub output_dir: std::path::PathBuf,
    pub target_arch: TargetArch,
    pub build_profile: String,
    pub include_assets: bool,
    pub environment: Option<String>,
    pub custom_metadata: HashMap<String, serde_json::Value>,
}

impl Default for PackageConfig {
    fn default() -> Self {
        Self {
            output_dir: std::path::PathBuf::from("target/packages"),
            target_arch: TargetArch::default_for_platform(),
            build_profile: "release".to_string(),
            include_assets: true,
            environment: None,
            custom_metadata: HashMap::new(),
        }
    }
}
