
use std::{io::Cursor, path::PathBuf};
use pyo3::{prelude::*, types::PyTuple};

use core_api::io::PayloadReader;

pub mod io;
pub mod io_ht;
pub mod io_readinto;
pub mod io_writeinto;

pub use io::*;
pub use io_ht::*;
pub use io_readinto::*;
pub use io_writeinto::*;

use crate::{PyHeaderV1, PyStreamError};

// #[pyclass]
// pub enum InputSource {
//     Reader,              // simplified: not exposing Box<dyn Read>
//     File(PathBuf),
//     Memory(Vec<u8>),
// }

// #[pyclass]
// pub enum OutputSink {
//     Writer,              // simplified: not exposing Box<dyn Write>
//     File(PathBuf),
//     Memory,
// }

// #[pymethods]
// impl InputSource {
//     #[new]
//     fn new_memory(data: &PyBytes) -> Self {
//         InputSource::Memory(data.as_bytes().to_vec())
//     }

//     #[staticmethod]
//     fn from_file(path: String) -> Self {
//         InputSource::File(PathBuf::from(path))
//     }
// }

// #[pymethods]
// impl OutputSink {
//     #[staticmethod]
//     fn memory() -> Self {
//         OutputSink::Memory
//     }

//     #[staticmethod]
//     fn file(path: String) -> Self {
//         OutputSink::File(PathBuf::from(path))
//     }

//     #[staticmethod]
//     fn writer() -> Self {
//         OutputSink::Writer
//     }
// }

// # 1️⃣ Python-side enums (PyO3 layer)

/// Python-side input abstraction
pub enum PyInputSource {
    Bytes(PyObject),
    ByteArray(PyObject),
    File(PathBuf),
    Reader(PyObject),
}

/// Python-side output abstraction
pub enum PyOutputSink {
    Memory,
    File(PathBuf),
    Writer(PyObject),
}


#[pyclass(name="PayloadReader")]
pub struct PyPayloadReader {
    _inner: PayloadReader<Cursor<Vec<u8>>>,
}

#[pymethods]
impl PyPayloadReader {
    #[staticmethod]
    pub fn with_header(py: Python<'_>, data: Vec<u8>) -> PyResult<PyObject> {
        let cursor = Cursor::new(data);

        match PayloadReader::with_header(cursor) {
            Ok((header, reader)) => {
                let py_header = PyHeaderV1::from(header).into_py(py);
                let py_reader = PyPayloadReader { _inner: reader }.into_py(py);

                Ok(PyTuple::new_bound(py, &[py_header, py_reader]).into())
            }
            Err(e) => Err(PyErr::from(PyStreamError::from(e))),
        }
    }
}

#[pymodule(name = "io")]
pub fn register_io(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {

    // Register class
    m.add_class::<PyPayloadReader>()?;

    Ok(())
}
