use anyhow::{Context, Result};
use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::Path;

/// 同義詞擴展器
/// 從 JSON 檔案加載自定義同義詞映射
#[derive(Debug, Clone, Default)]
pub struct SynonymExpander {
    /// 詞語 -> 同義詞列表的映射
    map: HashMap<String, Vec<String>>,
}

impl SynonymExpander {
    /// 從 JSON 檔案創建同義詞擴展器
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        let content = fs::read_to_string(path).context("Failed to read synonym file")?;
        let map: HashMap<String, Vec<String>> =
            serde_json::from_str(&content).context("Failed to parse synonym JSON")?;
        Ok(Self { map })
    }

    /// 從多個 JSON 檔案創建同義詞擴展器（後面的檔案會覆蓋前面的）
    pub fn from_files<P: AsRef<Path>>(paths: &[P]) -> Result<Self> {
        let mut combined_map = HashMap::new();

        for path in paths {
            let content = fs::read_to_string(path)
                .with_context(|| format!("Failed to read synonym file: {:?}", path.as_ref()))?;
            let map: HashMap<String, Vec<String>> =
                serde_json::from_str(&content).with_context(|| {
                    format!("Failed to parse synonym JSON from {:?}", path.as_ref())
                })?;

            // 合併映射，後面的檔案覆蓋前面的
            for (key, synonyms) in map {
                combined_map.insert(key, synonyms);
            }
        }

        Ok(Self { map: combined_map })
    }

    /// 從內建預設資料創建（返回空映射，用戶可通過配置文件添加自定義同義詞）
    pub fn from_default() -> Self {
        Self::empty()
    }

    /// 獲取詞語的同義詞列表（如果存在）
    pub fn get_synonyms(&self, word: &str) -> Option<&[String]> {
        self.map.get(word).map(|v| v.as_slice())
    }

    /// 擴展查詢詞語：將詞語替換為 (詞語 OR 同義詞1 OR 同義詞2 ...)
    /// 如果沒有同義詞，返回原詞語
    pub fn expand_word(&self, word: &str) -> String {
        match self.get_synonyms(word) {
            Some(syns) if !syns.is_empty() => {
                let mut parts = vec![word.to_string()];
                parts.extend_from_slice(syns);
                format!("({})", parts.join(" | "))
            }
            _ => word.to_string(),
        }
    }

    /// 擴展整個查詢字符串（空格分隔的詞語）
    pub fn expand_query(&self, query: &str) -> String {
        query
            .split_whitespace()
            .map(|word| self.expand_word(word))
            .collect::<Vec<_>>()
            .join(" & ")
    }

    /// 對中文查詢進行智能擴展：先匹配已知同義詞，再對剩餘部分進行分詞
    pub fn expand_chinese_query(&self, query: &str) -> String {
        // 如果查詢很短，直接嘗試匹配整個查詢
        if query.chars().count() <= 4 {
            if let Some(syns) = self.get_synonyms(query) {
                let mut parts = vec![query.to_string()];
                parts.extend_from_slice(syns);
                return format!("({})", parts.join(" | "));
            }
        }

        // 嘗試在查詢中尋找已知的同義詞
        let mut expanded_parts = Vec::new();
        let mut remaining_query = query;
        let mut found_synonym = false;

        // 對同義詞鍵按長度降序排序（最長匹配優先）
        let mut keys: Vec<&String> = self.map.keys().collect();
        keys.sort_by_key(|b| std::cmp::Reverse(b.chars().count()));

        // 貪婪匹配：尋找最長的同義詞匹配
        while !remaining_query.is_empty() {
            let mut matched = false;

            for key in &keys {
                if remaining_query.starts_with(*key) {
                    // 找到匹配的同義詞
                    expanded_parts.push(self.expand_word(key));
                    remaining_query = &remaining_query[key.len()..];
                    found_synonym = true;
                    matched = true;
                    break;
                }
            }

            if !matched {
                // 沒有找到同義詞，跳過第一個字符，繼續嘗試
                let first_char_len = remaining_query.chars().next().map_or(0, |c| c.len_utf8());
                if first_char_len > 0 {
                    let next_part = &remaining_query[..first_char_len];
                    expanded_parts.push(next_part.to_string());
                    remaining_query = &remaining_query[first_char_len..];
                } else {
                    break;
                }
            }
        }

        if found_synonym {
            // 如果有找到同義詞，使用擴展後的查詢
            expanded_parts.join(" & ")
        } else {
            // 沒有找到同義詞，返回原查詢（稍後會進行分詞）
            query.to_string()
        }
    }

    /// 創建空的同義詞擴展器（無同義詞映射）
    pub fn empty() -> Self {
        Self {
            map: HashMap::new(),
        }
    }
}

/// 全局同義詞擴展器（懶加載）
static SYNONYM_EXPANDER: Lazy<SynonymExpander> = Lazy::new(|| {
    // 優先嘗試 MOMENTRY_SYNONYM_FILES（逗號分隔的多個檔案）
    if let Ok(files_var) = env::var("MOMENTRY_SYNONYM_FILES") {
        let file_paths: Vec<&str> = files_var
            .split(',')
            .map(|s| s.trim())
            .filter(|s| !s.is_empty())
            .collect();

        if !file_paths.is_empty() {
            match SynonymExpander::from_files(&file_paths) {
                Ok(expander) => {
                    tracing::info!(
                        "Loaded synonym expander from {} files: {:?}",
                        file_paths.len(),
                        file_paths
                    );
                    return expander;
                }
                Err(e) => {
                    tracing::warn!(
                        "Failed to load synonym expander from files {:?}: {}",
                        file_paths,
                        e
                    );
                    // 繼續嘗試單一檔案或使用預設
                }
            }
        }
    }

    // 回退到單一檔案 MOMENTRY_SYNONYM_FILE（向下兼容）
    if let Ok(file_path) = env::var("MOMENTRY_SYNONYM_FILE") {
        match SynonymExpander::from_file(&file_path) {
            Ok(expander) => {
                tracing::info!("Loaded synonym expander from {}", file_path);
                expander
            }
            Err(e) => {
                tracing::warn!("Failed to load synonym expander from {}: {}", file_path, e);
                SynonymExpander::empty()
            }
        }
    } else {
        // 使用預設同義詞（示例）
        SynonymExpander::from_default()
    }
});

/// 獲取全局同義詞擴展器實例
pub fn global_synonym_expander() -> &'static SynonymExpander {
    &SYNONYM_EXPANDER
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_expand_word() {
        let mut map = HashMap::new();
        map.insert(
            "電腦".to_string(),
            vec!["計算機".to_string(), "微机".to_string()],
        );
        map.insert(
            "工作".to_string(),
            vec!["任務".to_string(), "作業".to_string()],
        );
        let expander = SynonymExpander { map };

        assert_eq!(expander.expand_word("電腦"), "(電腦 | 計算機 | 微机)");
        assert_eq!(expander.expand_word("工作"), "(工作 | 任務 | 作業)");
        assert_eq!(expander.expand_word("未知"), "未知");
    }

    #[test]
    fn test_expand_query() {
        let mut map = HashMap::new();
        map.insert(
            "電腦".to_string(),
            vec!["計算機".to_string(), "微机".to_string()],
        );
        map.insert(
            "工作".to_string(),
            vec!["任務".to_string(), "作業".to_string()],
        );
        let expander = SynonymExpander { map };

        assert_eq!(
            expander.expand_query("電腦 工作"),
            "(電腦 | 計算機 | 微机) & (工作 | 任務 | 作業)"
        );
        assert_eq!(expander.expand_query("單個詞"), "單個詞");
        assert_eq!(expander.expand_query(""), "");
    }

    #[test]
    fn test_from_files_empty() {
        let paths: Vec<&str> = vec![];
        let expander = SynonymExpander::from_files(&paths).unwrap();
        assert!(expander.map.is_empty());
    }
}
