#[derive({{ derives }})]
{%- if serde_rename_all %}
#[serde(rename_all = "{{ serde_rename_all }}")]
{%- endif %}
{%- for attr in enum_attrs %}
#[{{ attr }}]
{%- endfor %}
pub enum {{ enum_name }} {
{%- for variant in variants %}
{%- if variant.has_pyo3_rename %}
    #[pyo3(name = "{{ variant.pyo3_name }}")]
{%- endif %}
{%- if variant.is_default %}
    #[default]
{%- endif %}
{%- if variant.serde_rename %}
    #[serde(rename = "{{ variant.serde_rename }}")]
{%- endif %}
    {{ variant.name }} = {{ variant.idx }},
{%- endfor %}
}
{%- if is_pyo3 %}

#[pymethods]
impl {{ enum_name }} {
    #[new]
    fn __new__(value: pyo3::Bound<'_, pyo3::PyAny>) -> pyo3::PyResult<Self> {
        use pyo3::prelude::*;
        // Try to extract as string first
        if let Ok(s) = value.extract::<&str>() {
            let s_lower = s.to_lowercase();
            match s_lower.as_str() {
{%- for variant in variants %}
                "{{ variant.name | lower }}" => return Ok(Self::{{ variant.name }}),
{%- if variant.wire_name and (variant.wire_name | lower) != (variant.name | lower) %}
                "{{ variant.wire_name | lower }}" => return Ok(Self::{{ variant.name }}),
{%- endif %}
{%- endfor %}
                _ => {}
            }
        }
        // Try to extract as integer (by discriminant value)
        if let Ok(n) = value.extract::<i32>() {
            match n {
{%- for variant in variants %}
                {{ variant.idx }} => return Ok(Self::{{ variant.name }}),
{%- endfor %}
                _ => {}
            }
        }
        let type_name = stringify!({{ enum_name }});
        Err(pyo3::exceptions::PyValueError::new_err(format!(
            "invalid value for {}: {:#?}. Expected variant name (str) or discriminant (int)",
            type_name, value
        )))
    }

{{ string_methods }}
}
{%- endif %}
