use crate::app_config::AppConfig;
use crate::constants::{ACCOUNT_TYPES, AccountTypeDesc};
use actix_web::HttpResponse;

/// Serve robots.txt (disallow ranking)
pub async fn robots_txt() -> HttpResponse {
    HttpResponse::Ok()
        .content_type("text/plain")
        .body("User-agent: *\nDisallow: /\n")
}

#[derive(serde::Serialize)]
pub struct LenConstraints {
    min: usize,
    max: usize,
}

impl LenConstraints {
    pub fn new(min: usize, max: usize) -> Self {
        Self { min, max }
    }
    pub fn not_empty(max: usize) -> Self {
        Self { min: 1, max }
    }
    pub fn max_only(max: usize) -> Self {
        Self { min: 0, max }
    }

    pub fn check_str(&self, s: &str) -> bool {
        s.len() >= self.min && s.len() <= self.max
    }

    pub fn check_u32(&self, v: u32) -> bool {
        v >= self.min as u32 && v <= self.max as u32
    }
}

#[derive(serde::Serialize)]
pub struct ServerConstraints {
    pub token_name: LenConstraints,
    pub token_ip_net: LenConstraints,
    pub token_max_inactivity: LenConstraints,
    pub account_name: LenConstraints,
    pub movement_label: LenConstraints,
    pub inbox_entry_label: LenConstraints,
    pub file_allowed_types: &'static [&'static str],
}

impl Default for ServerConstraints {
    fn default() -> Self {
        Self {
            token_name: LenConstraints::new(5, 255),
            token_ip_net: LenConstraints::max_only(44),
            token_max_inactivity: LenConstraints::new(3600, 3600 * 24 * 365),
            account_name: LenConstraints::not_empty(50),
            movement_label: LenConstraints::not_empty(200),
            inbox_entry_label: LenConstraints::max_only(200),
            file_allowed_types: &[
                "image/jpeg",
                "image/png",
                "image/webp",
                "image/gif",
                "application/pdf",
            ],
        }
    }
}

#[derive(serde::Serialize)]
struct ServerConfig {
    auth_disabled: bool,
    oidc_provider_name: &'static str,
    apk_download_url: &'static str,
    accounts_types: &'static [AccountTypeDesc],
    constraints: ServerConstraints,
}

impl Default for ServerConfig {
    fn default() -> Self {
        Self {
            auth_disabled: AppConfig::get().is_auth_disabled(),
            oidc_provider_name: AppConfig::get().openid_provider().name,
            apk_download_url: AppConfig::get().apk_download_url.as_str(),
            constraints: Default::default(),
            accounts_types: &ACCOUNT_TYPES,
        }
    }
}

/// Get server static configuration
pub async fn config() -> HttpResponse {
    HttpResponse::Ok().json(ServerConfig::default())
}
