use crate::errors::*;
use crate::faceembed::FaceEmbedder;
use error_stack::ResultExt;
use ndarray::{Array2, ArrayView4};
use std::path::Path;

#[derive(Debug)]
pub struct EmbeddingGenerator {
    // Placeholder - ORT implementation to be completed later
    _placeholder: (),
}

pub struct EmbeddingGeneratorBuilder {
    _model_data: Vec<u8>,
}

impl EmbeddingGeneratorBuilder {
    pub fn new(model: impl AsRef<[u8]>) -> crate::errors::Result<Self> {
        Ok(Self {
            _model_data: model.as_ref().to_vec(),
        })
    }

    pub fn with_execution_providers(self, _providers: Vec<String>) -> Self {
        self
    }

    pub fn with_intra_threads(self, _threads: usize) -> Self {
        self
    }

    pub fn with_inter_threads(self, _threads: usize) -> Self {
        self
    }

    pub fn build(self) -> crate::errors::Result<EmbeddingGenerator> {
        // TODO: Implement ORT session creation
        tracing::warn!("ORT FaceNet implementation is not yet complete");
        Ok(EmbeddingGenerator { _placeholder: () })
    }
}

impl EmbeddingGenerator {
    const INPUT_NAME: &'static str = "serving_default_input_6:0";
    const OUTPUT_NAME: &'static str = "StatefulPartitionedCall:0";

    pub fn builder<T: AsRef<[u8]>>() -> fn(
        T,
    ) -> std::result::Result<
        EmbeddingGeneratorBuilder,
        error_stack::Report<crate::errors::Error>,
    > {
        EmbeddingGeneratorBuilder::new
    }

    pub fn new(path: impl AsRef<Path>) -> crate::errors::Result<Self> {
        let model = std::fs::read(path)
            .change_context(Error)
            .attach_printable("Failed to read model file")?;
        Self::new_from_bytes(&model)
    }

    pub fn new_from_bytes(model: impl AsRef<[u8]>) -> crate::errors::Result<Self> {
        tracing::info!("Loading face embedding model from bytes");
        Self::builder()(model)?.build()
    }

    pub fn run_models(&self, _face: ArrayView4<u8>) -> crate::errors::Result<Array2<f32>> {
        // TODO: Implement ORT inference
        tracing::error!("ORT FaceNet inference not yet implemented");
        Err(Error).attach_printable("ORT FaceNet implementation is incomplete")
    }
}

impl FaceEmbedder for EmbeddingGenerator {
    fn run_models(&self, faces: ArrayView4<u8>) -> crate::errors::Result<Array2<f32>> {
        self.run_models(faces)
    }
}
