//! BotConfig::load implementation and the save_ambient_rooms helper.

use std::path::Path;

use super::BotConfig;

impl BotConfig {
    /// Load bot configuration from `.huskies/bot.toml`.
    ///
    /// Returns `None` if the file does not exist, fails to parse, has
    /// `enabled = false`, or specifies no room IDs.
    pub fn load(project_root: &Path) -> Option<Self> {
        let path = project_root.join(".huskies").join("bot.toml");
        if !path.exists() {
            return None;
        }
        let content = std::fs::read_to_string(&path)
            .map_err(|e| eprintln!("[matrix-bot] Failed to read bot.toml: {e}"))
            .ok()?;
        let mut config: BotConfig = toml::from_str(&content)
            .map_err(|e| eprintln!("[matrix-bot] Invalid bot.toml: {e}"))
            .ok()?;
        if !config.enabled {
            return None;
        }
        // Merge deprecated `room_id` (single string) into `room_ids` (list).
        if let Some(single) = config.room_id.take()
            && !config.room_ids.contains(&single)
        {
            config.room_ids.push(single);
        }

        if config.transport == "whatsapp" {
            if config.whatsapp_provider == "twilio" {
                // Validate Twilio-specific fields.
                if config
                    .twilio_account_sid
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: whatsapp_provider=\"twilio\" requires \
                         twilio_account_sid"
                    );
                    return None;
                }
                if config
                    .twilio_auth_token
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: whatsapp_provider=\"twilio\" requires \
                         twilio_auth_token"
                    );
                    return None;
                }
                if config
                    .twilio_whatsapp_number
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: whatsapp_provider=\"twilio\" requires \
                         twilio_whatsapp_number"
                    );
                    return None;
                }
            } else {
                // Validate Meta (default) WhatsApp fields.
                if config
                    .whatsapp_phone_number_id
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: transport=\"whatsapp\" requires \
                         whatsapp_phone_number_id"
                    );
                    return None;
                }
                if config
                    .whatsapp_access_token
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: transport=\"whatsapp\" requires \
                         whatsapp_access_token"
                    );
                    return None;
                }
                if config
                    .whatsapp_verify_token
                    .as_ref()
                    .is_none_or(|s| s.is_empty())
                {
                    eprintln!(
                        "[bot] bot.toml: transport=\"whatsapp\" requires \
                         whatsapp_verify_token"
                    );
                    return None;
                }
            }
        } else if config.transport == "slack" {
            // Validate Slack-specific fields.
            if config.slack_bot_token.as_ref().is_none_or(|s| s.is_empty()) {
                eprintln!(
                    "[bot] bot.toml: transport=\"slack\" requires \
                     slack_bot_token"
                );
                return None;
            }
            if config
                .slack_signing_secret
                .as_ref()
                .is_none_or(|s| s.is_empty())
            {
                eprintln!(
                    "[bot] bot.toml: transport=\"slack\" requires \
                     slack_signing_secret"
                );
                return None;
            }
            if config.slack_channel_ids.is_empty() {
                eprintln!(
                    "[bot] bot.toml: transport=\"slack\" requires \
                     at least one slack_channel_ids entry"
                );
                return None;
            }
        } else if config.transport == "discord" {
            // Validate Discord-specific fields.
            if config
                .discord_bot_token
                .as_ref()
                .is_none_or(|s| s.is_empty())
            {
                eprintln!(
                    "[bot] bot.toml: transport=\"discord\" requires \
                     discord_bot_token"
                );
                return None;
            }
            if config.discord_channel_ids.is_empty() {
                eprintln!(
                    "[bot] bot.toml: transport=\"discord\" requires \
                     at least one discord_channel_ids entry"
                );
                return None;
            }
        } else {
            // Default transport is Matrix — validate Matrix-specific fields.
            if config.homeserver.as_ref().is_none_or(|s| s.is_empty()) {
                eprintln!("[bot] bot.toml: transport=\"matrix\" requires homeserver");
                return None;
            }
            if config.username.as_ref().is_none_or(|s| s.is_empty()) {
                eprintln!("[bot] bot.toml: transport=\"matrix\" requires username");
                return None;
            }
            if config.password.as_ref().is_none_or(|s| s.is_empty()) {
                eprintln!("[bot] bot.toml: transport=\"matrix\" requires password");
                return None;
            }
            if config.room_ids.is_empty() {
                eprintln!(
                    "[matrix-bot] bot.toml has no room_ids configured — \
                     add `room_ids = [\"!roomid:example.com\"]` to bot.toml"
                );
                return None;
            }
        }
        Some(config)
    }

    /// Returns all configured room IDs as a flat list. Combines `room_ids`
    /// and (after loading) any merged `room_id` value.
    pub fn effective_room_ids(&self) -> &[String] {
        &self.room_ids
    }
}

/// Persist the current set of ambient room IDs back to `bot.toml`.
///
/// Reads the existing file as a TOML document, updates the `ambient_rooms`
/// array, and writes the result back.  Errors are logged but not propagated
/// so a persistence failure never interrupts the bot's message handling.
pub fn save_ambient_rooms(project_root: &Path, room_ids: &[String]) {
    let path = project_root.join(".huskies").join("bot.toml");
    let content = match std::fs::read_to_string(&path) {
        Ok(c) => c,
        Err(e) => {
            eprintln!("[matrix-bot] save_ambient_rooms: failed to read bot.toml: {e}");
            return;
        }
    };
    let mut doc: toml::Value = match toml::from_str(&content) {
        Ok(v) => v,
        Err(e) => {
            eprintln!("[matrix-bot] save_ambient_rooms: failed to parse bot.toml: {e}");
            return;
        }
    };
    if let toml::Value::Table(ref mut t) = doc {
        let arr = toml::Value::Array(
            room_ids
                .iter()
                .map(|s| toml::Value::String(s.clone()))
                .collect(),
        );
        t.insert("ambient_rooms".to_string(), arr);
    }
    match toml::to_string_pretty(&doc) {
        Ok(new_content) => {
            if let Err(e) = std::fs::write(&path, new_content) {
                eprintln!("[matrix-bot] save_ambient_rooms: failed to write bot.toml: {e}");
            }
        }
        Err(e) => eprintln!("[matrix-bot] save_ambient_rooms: failed to serialise bot.toml: {e}"),
    }
}
