📄 src/receipt_printer_service.rs
use tonic::{Request, Response, Status};

use crate::proto::print_request::Content;
use crate::proto::receipt_printer_server;
use crate::proto::{PrintRequest, PrintResponse, TypstContent};
use crate::receipt_printer::ReceiptPrinter;
use crate::typst_renderer::render_typst_receipt;

pub struct ReceiptPrinterService {
    template_path: String,
    receipt_printer: ReceiptPrinter,
}

impl ReceiptPrinterService {
    pub fn new(template_path: String, receipt_printer: ReceiptPrinter) -> Self {
        Self {
            template_path,
            receipt_printer,
        }
    }
}

#[tonic::async_trait]
impl receipt_printer_server::ReceiptPrinter for ReceiptPrinterService {
    async fn print(
        &self,
        request: Request<PrintRequest>,
    ) -> Result<Response<PrintResponse>, Status> {
        let Some(Content::Typst(TypstContent {
            content: Some(content),
        })) = &request.get_ref().content
        else {
            return Err(Status::invalid_argument("No Typst content received"));
        };

        let image = match render_typst_receipt(self.template_path.as_ref(), content) {
            Ok(image) => image,
            Err(error) => {
                return Err(Status::internal(format!(
                    "Error rendering receipt: {error}"
                )));
            }
        };

        if let Err(error) = self.receipt_printer.print_image(image.into()).await {
            return Err(Status::internal(format!("Error when printing: {error}")));
        }

        Ok(Response::new(PrintResponse::default()))
    }
}