use std::borrow::Cow;

use arrow::array::{Array, BinaryArray, LargeBinaryArray};
use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
use pyo3::types::PyList;

pub(crate) fn append_binary_as_utf8<'py>(
    py: Python<'py>,
    out: &Bound<'py, PyList>,
    array: &dyn Array,
    large: bool,
) -> PyResult<()> {
    let len = array.len();
    for i in 0..len {
        if array.is_null(i) {
            out.append(py.None())?;
        } else {
            out.append(binary_as_utf8(array, i, large)?)?;
        }
    }
    Ok(())
}

pub(crate) fn binary_as_utf8<'a>(
    array: &'a dyn Array,
    row: usize,
    large: bool,
) -> PyResult<Cow<'a, str>> {
    let bytes = if large {
        let array = array
            .as_any()
            .downcast_ref::<LargeBinaryArray>()
            .ok_or_else(|| PyTypeError::new_err("expected LargeBinaryArray"))?;
        array.value(row)
    } else {
        let array = array
            .as_any()
            .downcast_ref::<BinaryArray>()
            .ok_or_else(|| PyTypeError::new_err("expected BinaryArray"))?;
        array.value(row)
    };
    Ok(String::from_utf8_lossy(bytes))
}
