//! fluent i18n module
use std::fmt::{Display, Write};

use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
use unic_langid::LanguageIdentifier;

/// AUTO-GENERATED BY Kam/scripts/add_missing_docs.py: placeholder documentation for public enum 'Language'. Replace with real documentation. (2025-12-30T22:23:21Z)
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub enum Language {
    #[default]
    /// AUTO-GENERATED BY Kam/scripts/add_missing_docs.py: placeholder documentation for public enum variant 'En' in 'Language'. Replace with real documentation. (2025-12-30T22:23:21Z)
    En,
    /// AUTO-GENERATED BY Kam/scripts/add_missing_docs.py: placeholder documentation for public enum variant 'Zh' in 'Language'. Replace with real documentation. (2025-12-30T22:23:21Z)
    Zh,
}

const EN_FTL: &str = include_str!("locales/en-US/main.ftl");
const ZH_FTL: &str = include_str!("locales/zh-CN/main.ftl");

fn dotted_to_ftl_id(key: &str) -> String {
    key.replace(&['.', '_'][..], "-")
}

/// Format a pattern using "{}" placeholders. This is a fallback used when the
/// supplied key is not a dotted translation id (or no FTL entry exists).
fn format_with_braces(format_str: &str, args: &[&dyn Display]) -> String {
    let mut out = String::new();
    let mut rest = format_str;
    let mut arg_iter = args.iter();
    while let Some(pos) = rest.find("{}") {
        out.push_str(&rest[..pos]);
        if let Some(arg) = arg_iter.next() {
            let _ = write!(out, "{arg}");
        } else {
            out.push_str("{}");
        }
        rest = &rest[pos + 2..];
    }
    out.push_str(rest);
    // Append any leftover args separated by space
    for arg in arg_iter {
        out.push(' ');
        let _ = write!(out, "{arg}");
    }
    out
}

/// Try to format a message using an FTL string and an explicit locale.
/// This constructs a FluentBundle on-demand (no static global bundles),
/// formats the message with named args ($arg0, $arg1, ...), and returns the result.
fn try_format_with_ftl(locale: &str, ftl: &str, id: &str, args: &[&dyn Display]) -> Option<String> {
    let lang: LanguageIdentifier = locale
        .parse()
        .unwrap_or_else(|_| LanguageIdentifier::default());
    let mut bundle = FluentBundle::new(vec![lang]);
    bundle.set_use_isolating(false);
    if let Ok(resource) = FluentResource::try_new(ftl.to_string()) {
        let _ = bundle.add_resource(resource);
    }
    if let Some(message) = bundle.get_message(id)
        && let Some(value) = message.value()
    {
        let mut fargs = FluentArgs::new();
        for (i, arg) in args.iter().enumerate() {
            let key = format!("arg{i}");
            fargs.set(key, FluentValue::from(arg.to_string()));
        }
        let mut errors = Vec::new();
        let s = bundle
            .format_pattern(value, Some(&fargs), &mut errors)
            .to_string();
        return Some(s);
    }
    None
}

/// Format a message key with optional arguments. Supports two modes:
/// - dotted translation keys (e.g. `validate.validating`) are looked up from FTL
///   resources (en → zh fallback).
/// - non-dotted strings are treated as format strings using `{}` placeholders.
pub fn tr_fmt(key: &str, args: &[&dyn Display]) -> String {
    if key.contains('.') {
        let id = dotted_to_ftl_id(key);

        // Determine preferred locale order:
        // Priority (highest → lowest):
        // 1) Explicit env var `KAM_UI_LANGUAGE`
        // 2) Project/local config (ui.language or language) or global config (via config module)
        // 3) System `LANG`
        // If any indicates Chinese, prefer zh-CN first.
        let prefer_zh = if let Ok(v) = std::env::var("KAM_UI_LANGUAGE") {
            v.to_lowercase().contains("zh")
        } else if let Some(cfg_lang) = crate::cmds::config::read_language_from_config() {
            cfg_lang.to_lowercase().contains("zh")
        } else if let Ok(v) = std::env::var("LANG") {
            v.to_lowercase().contains("zh")
        } else {
            false
        };

        if prefer_zh {
            if let Some(s) = try_format_with_ftl("zh-CN", ZH_FTL, &id, args) {
                return s;
            }
            if let Some(s) = try_format_with_ftl("en-US", EN_FTL, &id, args) {
                return s;
            }
        } else {
            if let Some(s) = try_format_with_ftl("en-US", EN_FTL, &id, args) {
                return s;
            }
            if let Some(s) = try_format_with_ftl("zh-CN", ZH_FTL, &id, args) {
                return s;
            }
        }
    }
    // Fallback to naive `{}` replacement if no FTL entry exists or key is non-dotted.
    format_with_braces(key, args)
}

/// Simple translation helper (no formatting). For dotted keys this attempts to
/// return the compiled FTL message; otherwise it returns the provided string.
#[must_use]
pub fn tr(key: &str) -> String {
    // Delegate to `tr_fmt`. Use an explicit empty slice cast here rather than
    // relying on a const or array-to-slice coercion because rust-analyzer
    // sometimes reports a spurious type mismatch for zero-length arrays.
    tr_fmt(key, &[] as &[&dyn Display])
}

/// Ensure the i18n subsystem is initialized.
///
/// Old callers expect an `init()` function to exist; with the current
/// on-demand design this is effectively a no-op but kept for compatibility and
/// future initialization needs.
pub const fn init() {
    // intentionally no-op
}
