use owly_news_module_api::{cstr_to_str, string_to_cstring_ptr};
use serde::{Deserialize, Serialize};
use std::os::raw::c_char;

#[derive(Deserialize)]
struct SummarizeReq {
    text: String,
    #[serde(default = "default_ratio")]
    ratio: f32,
}

fn default_ratio() -> f32 { 0.2 }

#[derive(Serialize)]
struct SummarizeResp {
    summary: String,
}

#[unsafe(no_mangle)]
pub extern "C" fn module_name() -> *const c_char {
    // IMPORTANT: string must live forever; use a const C string
    static NAME: &str = "summarizer\0";
    NAME.as_ptr() as *const c_char
}

#[unsafe(no_mangle)]
pub extern "C" fn module_invoke(op: *const c_char, payload: *const c_char) -> *mut c_char {
    // SAFETY: called by trusted host with valid pointers
    let res = (|| -> anyhow::Result<String> {
        let op = unsafe { cstr_to_str(op)? };
        let payload = unsafe { cstr_to_str(payload)? };

        match op {
            "summarize" => {
                let req: SummarizeReq = serde_json::from_str(payload)?;
                // Placeholder summarization logic. Replace with real algorithm.
                let words: Vec<&str> = req.text.split_whitespace().collect();
                let take = ((words.len() as f32) * req.ratio).max(1.0).round() as usize;
                let summary = words.into_iter().take(take).collect::<Vec<_>>().join(" ");
                let resp = SummarizeResp { summary };
                Ok(serde_json::to_string(&resp)?)
            }
            _ => anyhow::bail!("unknown op: {op}"),
        }
    })();

    let json = res.unwrap_or_else(|e| serde_json::json!({ "error": e.to_string() }).to_string());

    string_to_cstring_ptr(json)
}
