use arma_rs::{FromArma, IntoArma};
use forge_shared::OrgValidationError;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Org {
    pub id: String,
    pub owner: String,
    pub name: String,

    #[serde(default)]
    pub funds: f64,
    #[serde(default)]
    pub reputation: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemberSummary {
    pub uid: String,
    pub name: String,
}

impl Org {
    pub fn new<S: Into<String>>(id: S, owner: S, name: S) -> Result<Self, OrgValidationError> {
        let org = Self {
            id: id.into(),
            owner: owner.into(),
            name: name.into(),
            funds: 0.0,
            reputation: 0,
        };

        org.validate()?;
        Ok(org)
    }

    pub fn validate(&self) -> Result<(), OrgValidationError> {
        if self.id.trim().is_empty() {
            return Err(OrgValidationError::EmptyId);
        }

        if self.owner.trim().is_empty() {
            return Err(OrgValidationError::EmptyOwner);
        }

        if self.name.trim().is_empty() {
            return Err(OrgValidationError::EmptyName);
        }

        if self.funds < 0.0 {
            return Err(OrgValidationError::NegativeFunds);
        }

        if !self.id.chars().all(|c| c.is_alphanumeric() || c == '_') {
            return Err(OrgValidationError::InvalidId(self.id.clone()));
        }

        if self.owner != "server"
            && (!self.owner.chars().all(|c| c.is_numeric()) || self.owner.len() != 17)
        {
            return Err(OrgValidationError::InvalidOwner(self.owner.clone()));
        }

        if self.name.len() > 100 || self.name.chars().any(|c| c.is_control()) {
            return Err(OrgValidationError::InvalidName(self.name.clone()));
        }

        Ok(())
    }

    pub fn id(&self) -> &str {
        &self.id
    }
}

impl FromArma for Org {
    fn from_arma(s: String) -> Result<Self, arma_rs::FromArmaError> {
        serde_json::from_str(&s)
            .map_err(|e| arma_rs::FromArmaError::InvalidPrimitive(format!("Invalid JSON: {}", e)))
    }
}

impl IntoArma for Org {
    fn to_arma(&self) -> arma_rs::Value {
        let json_str = serde_json::to_string(self).unwrap_or_default();
        arma_rs::Value::String(json_str)
    }
}
