// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::collections::BTreeMap;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use iggy::prelude::{
    HeaderField, HeaderKey as RustHeaderKey, HeaderKind, HeaderValue as RustHeaderValue,
};
use pyo3::PyClass;
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::pyclass::CompareOp;
use pyo3::types::{PyBool, PyBytes, PyDict, PyFloat, PyInt, PyString, PyTuple};
use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pyclass_complex_enum, gen_stub_pymethods};

type RustUserHeaders = BTreeMap<RustHeaderKey, RustHeaderValue>;

#[derive(PartialEq, Eq, Hash)]
struct HeaderIdentity {
    kind: u8,
    value: Vec<u8>,
}

impl HeaderIdentity {
    fn raw(value: Vec<u8>) -> Self {
        Self {
            kind: HeaderKind::Raw.as_code(),
            value,
        }
    }

    fn string(value: Vec<u8>) -> Self {
        Self {
            kind: HeaderKind::String.as_code(),
            value,
        }
    }

    fn bool(value: bool) -> Self {
        Self {
            kind: HeaderKind::Bool.as_code(),
            value: vec![u8::from(value)],
        }
    }

    fn int8(value: i8) -> Self {
        Self {
            kind: HeaderKind::Int8.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn int16(value: i16) -> Self {
        Self {
            kind: HeaderKind::Int16.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn int32(value: i32) -> Self {
        Self {
            kind: HeaderKind::Int32.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn int64(value: i64) -> Self {
        Self {
            kind: HeaderKind::Int64.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn int128(value: i128) -> Self {
        Self {
            kind: HeaderKind::Int128.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn uint8(value: u8) -> Self {
        Self {
            kind: HeaderKind::Uint8.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn uint16(value: u16) -> Self {
        Self {
            kind: HeaderKind::Uint16.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn uint32(value: u32) -> Self {
        Self {
            kind: HeaderKind::Uint32.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn uint64(value: u64) -> Self {
        Self {
            kind: HeaderKind::Uint64.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn uint128(value: u128) -> Self {
        Self {
            kind: HeaderKind::Uint128.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn float32(value: f32) -> Self {
        Self {
            kind: HeaderKind::Float32.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }

    fn float64(value: f64) -> Self {
        Self {
            kind: HeaderKind::Float64.as_code(),
            value: value.to_le_bytes().to_vec(),
        }
    }
}

#[gen_stub_pyclass_complex_enum]
#[pyclass]
/// Typed key for an Iggy user header.
///
/// Use these constructors when the header key must preserve an explicit
/// wire type instead of using the common string-key dictionary form.
pub enum HeaderKey {
    /// Raw bytes key. The byte length must be 1..=255.
    Raw { value: Py<PyBytes> },
    /// UTF-8 string key. The encoded byte length must be 1..=255.
    String { value: String },
    /// Boolean key.
    Bool { value: bool },
    /// Signed 8-bit integer key.
    Int8 { value: i8 },
    /// Signed 16-bit integer key.
    Int16 { value: i16 },
    /// Signed 32-bit integer key.
    Int32 { value: i32 },
    /// Signed 64-bit integer key.
    Int64 { value: i64 },
    /// Signed 128-bit integer key.
    Int128 { value: i128 },
    /// Unsigned 8-bit integer key.
    UnsignedInt8 { value: u8 },
    /// Unsigned 16-bit integer key.
    UnsignedInt16 { value: u16 },
    /// Unsigned 32-bit integer key.
    UnsignedInt32 { value: u32 },
    /// Unsigned 64-bit integer key.
    UnsignedInt64 { value: u64 },
    /// Unsigned 128-bit integer key.
    UnsignedInt128 { value: u128 },
    /// 32-bit floating point key.
    Float32 { value: f32 },
    /// 64-bit floating point key.
    Float64 { value: f64 },
}

#[gen_stub_pyclass_complex_enum]
#[pyclass]
/// Typed value for an Iggy user header.
///
/// Use these constructors when the header value must preserve an explicit
/// wire type instead of using the common Python scalar dictionary form.
pub enum HeaderValue {
    /// Raw bytes value. The byte length must be 1..=255.
    Raw { value: Py<PyBytes> },
    /// UTF-8 string value. The encoded byte length must be 1..=255.
    String { value: String },
    /// Boolean value.
    Bool { value: bool },
    /// Signed 8-bit integer value.
    Int8 { value: i8 },
    /// Signed 16-bit integer value.
    Int16 { value: i16 },
    /// Signed 32-bit integer value.
    Int32 { value: i32 },
    /// Signed 64-bit integer value.
    Int64 { value: i64 },
    /// Signed 128-bit integer value.
    Int128 { value: i128 },
    /// Unsigned 8-bit integer value.
    UnsignedInt8 { value: u8 },
    /// Unsigned 16-bit integer value.
    UnsignedInt16 { value: u16 },
    /// Unsigned 32-bit integer value.
    UnsignedInt32 { value: u32 },
    /// Unsigned 64-bit integer value.
    UnsignedInt64 { value: u64 },
    /// Unsigned 128-bit integer value.
    UnsignedInt128 { value: u128 },
    /// 32-bit floating point value.
    Float32 { value: f32 },
    /// 64-bit floating point value.
    Float64 { value: f64 },
}

trait PyHeaderFieldToRust: PyClass + Sized {
    type RustType;
    fn from_pyheader(py: Python<'_>, value: &Self) -> PyResult<Self::RustType>;
    fn from_plain(field: &Bound<'_, PyAny>) -> PyResult<Option<Self::RustType>>;
}

fn py_header_field_to_rust<T: PyHeaderFieldToRust>(
    py: Python<'_>,
    field: &Bound<'_, PyAny>,
) -> PyResult<T::RustType> {
    if let Ok(header) = field.extract::<PyRef<'_, T>>() {
        return T::from_pyheader(py, &header);
    }
    T::from_plain(field)?.ok_or_else(|| {
        PyValueError::new_err(
            "User header must be str, bytes, bool, int, float, HeaderKey, or HeaderValue",
        )
    })
}

trait ToPlain {
    fn to_plain<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>;
}

/// Borrows a typed header ([`HeaderKey`] or [`HeaderValue`]) together with the
/// GIL token for direct conversion to a plain Python scalar.
struct HeaderToPlainRef<'py, 'value, T: ToPlain> {
    py: Python<'py>,
    value: &'value T,
}

impl<'py, T: ToPlain> TryFrom<HeaderToPlainRef<'py, '_, T>> for Bound<'py, PyAny> {
    type Error = PyErr;

    fn try_from(inner: HeaderToPlainRef<'py, '_, T>) -> PyResult<Self> {
        let HeaderToPlainRef { py, value } = inner;
        value.to_plain(py)
    }
}

macro_rules! header_type_impl {
    ($py_ty:ident) => {
        paste::paste! {
            #[gen_stub_pymethods]
            #[pymethods]
            impl $py_ty {
                pub fn __hash__(&self, py: Python<'_>) -> PyResult<isize> {
                    Ok(py_hash(header_identity_hash(self.identity(py)?)))
                }

                pub fn __richcmp__(
                    &self,
                    py: Python<'_>,
                    other: &Bound<'_, PyAny>,
                    op: CompareOp,
                ) -> PyResult<Py<PyAny>> {
                    let identity = self.identity(py)?;
                    let Ok(other_header) = other.extract::<PyRef<'_, $py_ty>>() else {
                        return match op {
                            CompareOp::Eq => {
                                Ok(false.into_pyobject(py)?.to_owned().into_any().unbind())
                            }
                            CompareOp::Ne => {
                                Ok(true.into_pyobject(py)?.to_owned().into_any().unbind())
                            }
                            _ => Ok(py.NotImplemented()),
                        };
                    };
                    let result = match op {
                        CompareOp::Eq => identity == other_header.identity(py)?,
                        CompareOp::Ne => identity != other_header.identity(py)?,
                        _ => return Ok(py.NotImplemented()),
                    };
                    Ok(result.into_pyobject(py)?.to_owned().into_any().unbind())
                }

                pub fn __repr__(&self, py: Python<'_>) -> PyResult<String> {
                    self.repr(py)
                }
            }

            struct [<Py $py_ty Ref>]<'py, 'value> {
                py: Python<'py>,
                value: &'value $py_ty,
            }

            impl TryFrom<[<Py $py_ty Ref>]<'_, '_>> for [<Rust $py_ty>] {
                type Error = PyErr;

                fn try_from(value: [<Py $py_ty Ref>]<'_, '_>) -> PyResult<Self> {
                    let [<Py $py_ty Ref>] { py, value } = value;
                    match value {
                        $py_ty::Raw { value } => {
                            <[<Rust $py_ty>]>::try_from(value.extract::<Vec<u8>>(py)?)
                                .map_err(to_value_error)
                        }
                        $py_ty::String { value } => {
                            <[<Rust $py_ty>]>::try_from(value.as_str()).map_err(to_value_error)
                        }
                        $py_ty::Bool { value } => Ok((*value).into()),
                        $py_ty::Int8 { value } => Ok((*value).into()),
                        $py_ty::Int16 { value } => Ok((*value).into()),
                        $py_ty::Int32 { value } => Ok((*value).into()),
                        $py_ty::Int64 { value } => Ok((*value).into()),
                        $py_ty::Int128 { value } => Ok((*value).into()),
                        $py_ty::UnsignedInt8 { value } => Ok((*value).into()),
                        $py_ty::UnsignedInt16 { value } => Ok((*value).into()),
                        $py_ty::UnsignedInt32 { value } => Ok((*value).into()),
                        $py_ty::UnsignedInt64 { value } => Ok((*value).into()),
                        $py_ty::UnsignedInt128 { value } => Ok((*value).into()),
                        $py_ty::Float32 { value } => checked_float32(*value),
                        $py_ty::Float64 { value } => checked_float64(*value),
                    }
                }
            }

            struct [<Rust $py_ty Ref>]<'py, 'value> {
                py: Python<'py>,
                value: &'value [<Rust $py_ty>],
            }

            impl<'py> TryFrom<[<Rust $py_ty Ref>]<'py, '_>> for Bound<'py, $py_ty> {
                type Error = PyErr;

                fn try_from(value: [<Rust $py_ty Ref>]<'py, '_>) -> PyResult<Self> {
                    let [<Rust $py_ty Ref>] { py, value } = value;
                    let value = match value.kind() {
                        HeaderKind::Raw => $py_ty::Raw {
                            value: PyBytes::new(py, value.as_raw().map_err(to_value_error)?)
                                .unbind(),
                        },
                        HeaderKind::String => $py_ty::String {
                            value: value.as_str().map_err(to_value_error)?.to_string(),
                        },
                        HeaderKind::Bool => $py_ty::Bool {
                            value: value.as_bool().map_err(to_value_error)?,
                        },
                        HeaderKind::Int8 => $py_ty::Int8 {
                            value: value.as_int8().map_err(to_value_error)?,
                        },
                        HeaderKind::Int16 => $py_ty::Int16 {
                            value: value.as_int16().map_err(to_value_error)?,
                        },
                        HeaderKind::Int32 => $py_ty::Int32 {
                            value: value.as_int32().map_err(to_value_error)?,
                        },
                        HeaderKind::Int64 => $py_ty::Int64 {
                            value: value.as_int64().map_err(to_value_error)?,
                        },
                        HeaderKind::Int128 => $py_ty::Int128 {
                            value: value.as_int128().map_err(to_value_error)?,
                        },
                        HeaderKind::Uint8 => $py_ty::UnsignedInt8 {
                            value: value.as_uint8().map_err(to_value_error)?,
                        },
                        HeaderKind::Uint16 => $py_ty::UnsignedInt16 {
                            value: value.as_uint16().map_err(to_value_error)?,
                        },
                        HeaderKind::Uint32 => $py_ty::UnsignedInt32 {
                            value: value.as_uint32().map_err(to_value_error)?,
                        },
                        HeaderKind::Uint64 => $py_ty::UnsignedInt64 {
                            value: value.as_uint64().map_err(to_value_error)?,
                        },
                        HeaderKind::Uint128 => $py_ty::UnsignedInt128 {
                            value: value.as_uint128().map_err(to_value_error)?,
                        },
                        HeaderKind::Float32 => {
                            let v = value.as_float32().map_err(to_value_error)?;
                            if !v.is_finite() {
                                return Err(PyValueError::new_err(
                                    "User header with non-finite Float32 value",
                                ));
                            }
                            $py_ty::Float32 { value: v }
                        },
                        HeaderKind::Float64 => {
                            let v = value.as_float64().map_err(to_value_error)?;
                            if !v.is_finite() {
                                return Err(PyValueError::new_err(
                                    "User header with non-finite Float64 value",
                                ));
                            }
                            $py_ty::Float64 { value: v }
                        },
                    };
                    value.into_pyobject(py)
                }
            }

            impl $py_ty {
                fn identity(&self, py: Python<'_>) -> PyResult<HeaderIdentity> {
                    match self {
                        $py_ty::Raw { value } => {
                            Ok(HeaderIdentity::raw(value.extract::<Vec<u8>>(py)?))
                        }
                        $py_ty::String { value } => {
                            Ok(HeaderIdentity::string(value.as_bytes().to_vec()))
                        }
                        $py_ty::Bool { value } => Ok(HeaderIdentity::bool(*value)),
                        $py_ty::Int8 { value } => Ok(HeaderIdentity::int8(*value)),
                        $py_ty::Int16 { value } => Ok(HeaderIdentity::int16(*value)),
                        $py_ty::Int32 { value } => Ok(HeaderIdentity::int32(*value)),
                        $py_ty::Int64 { value } => Ok(HeaderIdentity::int64(*value)),
                        $py_ty::Int128 { value } => Ok(HeaderIdentity::int128(*value)),
                        $py_ty::UnsignedInt8 { value } => Ok(HeaderIdentity::uint8(*value)),
                        $py_ty::UnsignedInt16 { value } => Ok(HeaderIdentity::uint16(*value)),
                        $py_ty::UnsignedInt32 { value } => Ok(HeaderIdentity::uint32(*value)),
                        $py_ty::UnsignedInt64 { value } => Ok(HeaderIdentity::uint64(*value)),
                        $py_ty::UnsignedInt128 { value } => Ok(HeaderIdentity::uint128(*value)),
                        $py_ty::Float32 { value } => Ok(HeaderIdentity::float32(*value)),
                        $py_ty::Float64 { value } => Ok(HeaderIdentity::float64(*value)),
                    }
                }

                fn repr(&self, py: Python<'_>) -> PyResult<String> {
                    match self {
                        $py_ty::Raw { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Raw({})"),
                            value.bind(py).repr()?.extract::<String>()?
                        )),
                        $py_ty::String { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".String({:?})"),
                            value
                        )),
                        $py_ty::Bool { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Bool({})"),
                            value
                        )),
                        $py_ty::Int8 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Int8({})"),
                            value
                        )),
                        $py_ty::Int16 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Int16({})"),
                            value
                        )),
                        $py_ty::Int32 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Int32({})"),
                            value
                        )),
                        $py_ty::Int64 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Int64({})"),
                            value
                        )),
                        $py_ty::Int128 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Int128({})"),
                            value
                        )),
                        $py_ty::UnsignedInt8 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".UnsignedInt8({})"),
                            value
                        )),
                        $py_ty::UnsignedInt16 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".UnsignedInt16({})"),
                            value
                        )),
                        $py_ty::UnsignedInt32 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".UnsignedInt32({})"),
                            value
                        )),
                        $py_ty::UnsignedInt64 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".UnsignedInt64({})"),
                            value
                        )),
                        $py_ty::UnsignedInt128 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".UnsignedInt128({})"),
                            value
                        )),
                        $py_ty::Float32 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Float32({:?})"),
                            value
                        )),
                        $py_ty::Float64 { value } => Ok(format!(
                            concat!(stringify!($py_ty), ".Float64({:?})"),
                            value
                        )),
                    }
                }
            }

            impl PyHeaderFieldToRust for $py_ty {
                type RustType = [<Rust $py_ty>];

                fn from_pyheader(py: Python<'_>, value: &Self) -> PyResult<[<Rust $py_ty>]> {
                    <[<Rust $py_ty>]>::try_from([<Py $py_ty Ref>] { py, value })
                }

                fn from_plain(field: &Bound<'_, PyAny>) -> PyResult<Option<[<Rust $py_ty>]>> {
                    plain_to_rust_header_field(field)
                }
            }

            impl ToPlain for $py_ty {
                fn to_plain<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
                    match self {
                        Self::Raw { value } => Ok(value.bind(py).clone().into_any()),
                        Self::String { value } => Ok(value.clone().into_pyobject(py)?.into_any()),
                        Self::Bool { value } => Ok((*value).into_pyobject(py)?.to_owned().into_any()),
                        Self::Int8 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::Int16 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::Int32 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::Int64 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::Int128 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::UnsignedInt8 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::UnsignedInt16 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::UnsignedInt32 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::UnsignedInt64 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::UnsignedInt128 { value } => Ok((*value).into_pyobject(py)?.into_any()),
                        Self::Float32 { value } => {
                            if !value.is_finite() {
                                return Err(PyValueError::new_err(
                                    "User header with non-finite Float32 value",
                                ));
                            }
                            Ok(f64::from(*value).into_pyobject(py)?.into_any())
                        },
                        Self::Float64 { value } => {
                            if !value.is_finite() {
                                return Err(PyValueError::new_err(
                                    "User header with non-finite Float64 value",
                                ));
                            }
                            Ok((*value).into_pyobject(py)?.into_any())
                        },
                    }
                }
            }
        }
    };
}

header_type_impl!(HeaderKey);
header_type_impl!(HeaderValue);

pub(crate) fn py_user_headers_to_rust(
    py: Python<'_>,
    mapping: &Bound<'_, PyAny>,
) -> PyResult<RustUserHeaders> {
    let mut rust_headers = BTreeMap::new();
    for item in mapping.call_method0("items")?.try_iter()? {
        let item = item?;
        let pair: &Bound<'_, PyTuple> = item.cast()?;
        let key = pair.get_item(0)?;
        let value = pair.get_item(1)?;
        let key = py_header_field_to_rust::<HeaderKey>(py, &key)?;
        let value = py_header_field_to_rust::<HeaderValue>(py, &value)?;
        if rust_headers.insert(key, value).is_some() {
            return Err(PyValueError::new_err(
                "Duplicate user header key: each header key must be unique",
            ));
        }
    }
    Ok(rust_headers)
}

/// Wrap one Rust header value as the `HeaderValue` message headers already use.
///
/// The option catalog reports each key's default as a typed value, and options
/// ride the user-headers codec, so they hand back the same type rather than a
/// second one that means the same thing.
pub(crate) fn rust_header_value_to_py<'a>(
    py: Python<'a>,
    value: &RustHeaderValue,
) -> PyResult<Bound<'a, HeaderValue>> {
    Bound::<HeaderValue>::try_from(RustHeaderValueRef { py, value })
}

pub(crate) fn rust_user_headers_to_py<'a>(
    py: Python<'a>,
    headers: RustUserHeaders,
) -> PyResult<Bound<'a, UserHeaders>> {
    let result = Bound::new(py, UserHeaders)?;
    let mapping = result.as_any();
    for (key, value) in headers {
        let key = Bound::<HeaderKey>::try_from(RustHeaderKeyRef { py, value: &key })?;
        let value = Bound::<HeaderValue>::try_from(RustHeaderValueRef { py, value: &value })?;
        mapping.set_item(key, value)?;
    }
    Ok(result)
}

/// User headers dictionary returned by `ReceiveMessage.user_headers`.
///
/// This is a regular `dict[HeaderKey, HeaderValue]` (so all mapping
/// operations work) that additionally exposes `to_scalar_dict` for the convenient
/// scalar form.
#[gen_stub_pyclass]
#[pyclass(extends=PyDict)]
pub struct UserHeaders;

#[gen_stub_pymethods]
#[pymethods]
impl UserHeaders {
    /// Wraps a mapping so its entries gain the `to_scalar_dict` helper.
    ///
    /// Accepts a dict whose keys and values can each independently be
    /// `HeaderKey`/`HeaderValue` or a plain scalar (`str | bytes | bool |
    /// int | float`). The inherited `dict` initializer copies the provided
    /// mapping.
    #[new]
    #[pyo3(signature = (mapping=None))]
    pub fn new(
        #[gen_stub(override_type(type_repr = "dict | None"))] mapping: Option<&Bound<'_, PyAny>>,
    ) -> PyResult<Self> {
        if let Some(mapping) = mapping {
            let py = mapping.py();
            py_user_headers_to_rust(py, mapping)?;
        }
        Ok(UserHeaders)
    }

    fn __setitem__(
        slf: &Bound<'_, Self>,
        key: &Bound<'_, PyAny>,
        value: &Bound<'_, PyAny>,
    ) -> PyResult<()> {
        let py = key.py();
        py_header_field_to_rust::<HeaderKey>(py, key)?;
        py_header_field_to_rust::<HeaderValue>(py, value)?;
        slf.as_any().cast::<PyDict>()?.set_item(key, value)?;
        Ok(())
    }

    /// Converts these headers into the convenient plain dictionary form.
    ///
    /// Returns an error if two distinct typed keys map to the same plain
    /// Python scalar (e.g., `UnsignedInt8(1)` and `UnsignedInt16(1)` both
    /// become `int(1)`), or if a stored field cannot be decoded.
    #[gen_stub(override_return_type(
        type_repr = "dict[str | bytes | bool | int | float, str | bytes | bool | int | float]"
    ))]
    pub fn to_scalar_dict<'a>(slf: &Bound<'a, Self>) -> PyResult<Bound<'a, PyDict>> {
        let py = slf.py();
        let dict = slf.as_any().cast::<PyDict>()?;
        let result = PyDict::new(py);
        for (key, value) in dict.iter() {
            let plain_key = py_header_to_plain::<HeaderKey>(py, &key)?;
            let plain_value = py_header_to_plain::<HeaderValue>(py, &value)?;
            if result.contains(&plain_key)? {
                return Err(PyValueError::new_err(
                    "Distinct typed header keys produce the same plain Python scalar; this conversion is lossy and cannot proceed",
                ));
            }
            result.set_item(plain_key, plain_value)?;
        }
        Ok(result)
    }
}

fn py_header_to_plain<'py, T: ToPlain + PyClass>(
    py: Python<'py>,
    any: &Bound<'py, PyAny>,
) -> PyResult<Bound<'py, PyAny>> {
    if let Ok(header) = any.extract::<PyRef<'_, T>>() {
        return Bound::<PyAny>::try_from(HeaderToPlainRef {
            py,
            value: &*header,
        });
    }
    if any.is_instance_of::<PyString>()
        || any.is_instance_of::<PyBytes>()
        || any.is_instance_of::<PyInt>()
        || any.is_instance_of::<PyFloat>()
    {
        return Ok(any.clone());
    }
    Err(PyValueError::new_err(
        "User header must be str, bytes, bool, int, float, HeaderKey, or HeaderValue",
    ))
}

/// Converts a plain Python scalar into a header field (used for both keys and
/// values). Returns `Ok(None)` when the object is not a supported plain type so
/// the caller can raise a message naming keys vs values; genuine range/length
/// errors are returned as `Err`.
fn plain_to_rust_header_field<T>(obj: &Bound<'_, PyAny>) -> PyResult<Option<HeaderField<T>>> {
    if obj.is_instance_of::<PyBool>() {
        return Ok(Some(obj.extract::<bool>()?.into()));
    }
    if obj.is_instance_of::<PyInt>() {
        return int_to_rust_header_field(obj).map(Some);
    }
    if obj.is_instance_of::<PyFloat>() {
        return float_to_rust_header_field(obj.extract::<f64>()?).map(Some);
    }
    if obj.is_instance_of::<PyString>() {
        return HeaderField::try_from(obj.extract::<String>()?)
            .map(Some)
            .map_err(to_value_error);
    }
    if obj.is_instance_of::<PyBytes>() {
        return HeaderField::try_from(obj.extract::<Vec<u8>>()?)
            .map(Some)
            .map_err(to_value_error);
    }
    Ok(None)
}

fn int_to_rust_header_field<T>(obj: &Bound<'_, PyAny>) -> PyResult<HeaderField<T>> {
    if let Ok(value) = obj.extract::<u8>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<u16>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<u32>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<u64>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<u128>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<i8>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<i16>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<i32>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<i64>() {
        return Ok(value.into());
    }
    if let Ok(value) = obj.extract::<i128>() {
        return Ok(value.into());
    }
    Err(PyValueError::new_err(
        "User header int values must fit within the 128-bit range",
    ))
}

fn float_to_rust_header_field<T>(value: f64) -> PyResult<HeaderField<T>> {
    if !value.is_finite() {
        return Err(PyValueError::new_err(
            "User header float values must be finite",
        ));
    }
    let narrowed = value as f32;
    if f64::from(narrowed) == value {
        checked_float32(narrowed)
    } else {
        Ok(value.into())
    }
}

fn checked_float32<T>(value: f32) -> PyResult<HeaderField<T>> {
    if !value.is_finite() {
        return Err(PyValueError::new_err(
            "Float32 header must be a finite value within the 32-bit float range",
        ));
    }
    Ok(value.into())
}

fn checked_float64<T>(value: f64) -> PyResult<HeaderField<T>> {
    if !value.is_finite() {
        return Err(PyValueError::new_err("Float64 header value must be finite"));
    }
    Ok(value.into())
}

fn header_identity_hash(identity: HeaderIdentity) -> u64 {
    let mut hasher = DefaultHasher::new();
    identity.hash(&mut hasher);
    hasher.finish()
}

fn py_hash(hash: u64) -> isize {
    let hash = hash as isize;
    if hash == -1 { -2 } else { hash }
}

fn to_value_error(error: impl ToString) -> PyErr {
    PyValueError::new_err(error.to_string())
}
