// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Feature Management Program Interface
//!
//! This program provides a system-level mechanism for managing feature flags
//! with time-based activation and deactivation schedules.

#![no_std]

extern crate alloc;

use alloc::vec::Vec;

use rialo_s_pubkey::Pubkey;

pub mod error;
pub mod instruction;
pub mod state;

rialo_s_pubkey::declare_id!("Feature1111111111111111111111111111111111111");

/// Storage account PDA seed for the features map
pub const STORAGE_ACCOUNT_SEED: &[u8] = b"features_storage";

/// Derive the storage account address
pub fn get_storage_account_address() -> (rialo_s_pubkey::Pubkey, u8) {
    rialo_s_pubkey::Pubkey::find_program_address(&[STORAGE_ACCOUNT_SEED], &id())
}

/// Maximum length for a feature name
pub const MAX_FEATURE_NAME_LENGTH: usize = 512;

/// Maximum number of features allowed in the system
pub const MAX_FEATURE_COUNT: usize = 10000;

/// Maximum total size of serialized features state (100 KB)
pub const MAX_FEATURES_STATE_SIZE: usize = 100 * 1024;

/// Validates a feature name
///
/// Feature names must:
/// - Not be empty
/// - Not exceed MAX_FEATURE_NAME_LENGTH
/// - Contain only alphanumeric characters, underscores, and hyphens
/// - Not start or end with whitespace
pub fn validate_feature_name(name: &str) -> bool {
    !name.is_empty()
        && name.len() <= MAX_FEATURE_NAME_LENGTH
        && name
            .chars()
            .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
        && !name.starts_with(char::is_whitespace)
        && !name.ends_with(char::is_whitespace)
}

/// Create genesis storage data with initial authority
///
/// Creates the initial FeaturesState with the provided authority and serializes it
/// for use in genesis configuration.
///
/// # Arguments
/// * `authority` - The pubkey that will have authority over the feature management system
///
/// # Returns
/// A `Vec<u8>` containing the serialized FeaturesState
pub fn genesis_storage(authority: Pubkey) -> Vec<u8> {
    use state::FeaturesState;

    let state = FeaturesState::new(authority);
    state
        .serialize()
        .expect("Failed to serialize genesis state")
}
