use pyo3::prelude::*;
use pyo3::types::{PyFloat, PyInt, PyString};

#[pyfunction]
fn parse(py: Python, input: &Bound<'_, PyAny>) -> PyResult<Option<PyObject>> {
    // 1. FAST EXIT: If input is already a number
    if input.is_instance_of::<PyInt>() || input.is_instance_of::<PyFloat>() {
        return Ok(Some(input.to_object(py)));
    }

    // 2. BORROW the string (Don't copy it!)
    let pystr = match input.downcast::<PyString>() {
        Ok(s) => s,
        Err(_) => return Ok(None),
    };
    let text = pystr.to_str()?; // Zero-copy view of the data

    if text.is_empty() { return Ok(None); }

    // 3. DETECT MULTIPLIER (Scan without modifying string)
    let mut multiplier = 1.0;
    // We scan bytes for speed. 'k' is byte 107.
    if text.contains(['k', 'K']) { multiplier = 1_000.0; }
    else if text.contains(['m', 'M']) { multiplier = 1_000_000.0; }
    else if text.contains(['b', 'B']) { multiplier = 1_000_000_000.0; }

    // 4. EXTRACT NUMBER MANUALLY
    // We create a small buffer on the stack/heap to hold just the digits.
    // "1,200.50" -> we only collect "1200.50"
    let mut num_buf = String::with_capacity(text.len());
    let mut found_digit = false;

    for c in text.chars() {
        match c {
            '0'..='9' | '.' => {
                found_digit = true;
                num_buf.push(c);
            }
            ',' => {
                // Skip commas entirely (effectively removing them)
                continue; 
            }
            _ => {
                // If we hit a weird character (like 'k' or ' ' or '$')...
                // If we haven't found a number yet, keep searching.
                // If we HAVE found a number, STOP. (This mimics regex \d+)
                if found_digit {
                    break; 
                }
            }
        }
    }

    if num_buf.is_empty() { return Ok(None); }

    // 5. PARSE & RETURN
    if let Ok(val) = num_buf.parse::<f64>() {
        let result = val * multiplier;
        
        if result.fract() == 0.0 {
            return Ok(Some((result as i64).to_object(py)));
        } else {
            return Ok(Some(result.to_object(py)));
        }
    }

    Ok(None)
}

// ✅ CORRECT NAME (Matches your error log)
#[pymodule]
fn _kidexa_fast(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(parse, m)?)?;
    Ok(())
}