use crate::models::ClientProvider;

use async_trait::async_trait;
use lettre::{
    message::header::ContentType, Message as LettreMessage, Transport,
};
use myc_core::domain::{
    dtos::message::{FromEmail, Message},
    entities::RemoteMessageWrite,
};
use mycelium_base::{
    entities::CreateResponseKind,
    utils::errors::{creation_err, MappedErrors},
};
use shaku::Component;
use std::sync::Arc;
use uuid::Uuid;

#[derive(Component)]
#[shaku(interface = RemoteMessageWrite)]
pub struct RemoteMessageSendingRepository {
    #[shaku(inject)]
    client: Arc<dyn ClientProvider>,
}

#[async_trait]
impl RemoteMessageWrite for RemoteMessageSendingRepository {
    #[tracing::instrument(name = "send", skip_all)]
    async fn send(
        &self,
        message: Message,
    ) -> Result<CreateResponseKind<Option<Uuid>>, MappedErrors> {
        let connection = self.client.get_smtp_client().as_ref().clone();

        let email = LettreMessage::builder()
            .from(
                (match message.to_owned().from {
                    FromEmail::Email(email) => email.email(),
                    FromEmail::NamedEmail(named_email) => named_email,
                })
                .parse()
                .unwrap(),
            )
            .to(message.to_owned().to.email().parse().unwrap())
            .subject(message.to_owned().subject)
            .header(ContentType::TEXT_HTML)
            .body(message.to_owned().body)
            .unwrap();

        match connection.send(&email) {
            Ok(_) => Ok(CreateResponseKind::Created(None)),
            Err(err) => {
                creation_err(format!("Could not send email: {err}")).as_error()
            }
        }
    }
}
