use tokio::sync::oneshot;
use uuid::Uuid;

use kordophone::model::ConversationID;
use kordophone::model::OutgoingMessage;
use kordophone_db::models::Conversation;

use crate::daemon::settings::Settings;
use crate::daemon::{Attachment, Message};

pub type Reply<T> = oneshot::Sender<T>;

use std::path::PathBuf;

#[derive(Debug)]
pub enum Event {
    /// Get the version of the daemon.
    GetVersion(Reply<String>),

    /// Asynchronous event for syncing the conversation list with the server.
    SyncConversationList(Reply<()>),

    /// Asynchronous event for syncing all conversations with the server.
    SyncAllConversations(Reply<()>),

    /// Asynchronous event for syncing a single conversation with the server.
    SyncConversation(String, Reply<()>),

    /// Asynchronous event for marking a conversation as read.
    MarkConversationAsRead(String, Reply<()>),

    /// Asynchronous event for updating the metadata for a conversation.
    UpdateConversationMetadata(Conversation, Reply<()>),

    /// Sent when the update stream is reconnected after a timeout or configuration change.
    UpdateStreamReconnected,

    /// Returns all known conversations from the database.
    /// Parameters:
    /// - limit: The maximum number of conversations to return. (-1 for no limit)
    /// - offset: The offset into the conversation list to start returning conversations from.
    GetAllConversations(i32, i32, Reply<Vec<Conversation>>),

    /// Returns all known settings from the database.
    GetAllSettings(Reply<Settings>),

    /// Update settings in the database.
    UpdateSettings(Settings, Reply<()>),

    /// Returns all messages for a conversation from the database.
    /// Parameters:
    /// - conversation_id: The ID of the conversation to get messages for.
    /// - last_message_id: (optional) The ID of the last message to get. If None, all messages are returned.
    GetMessages(String, Option<String>, Reply<Vec<Message>>),

    /// Enqueues a message to be sent to the server.
    /// Parameters:
    /// - conversation_id: The ID of the conversation to send the message to.
    /// - text: The text of the message to send.
    /// - attachment_guids: The GUIDs of the attachments to send.
    /// - reply: The outgoing message ID (not the server-assigned message ID).
    SendMessage(String, String, Vec<String>, Reply<Uuid>),

    /// Notifies the daemon that a message has been sent.
    /// Parameters:
    /// - message: The message that was sent.
    /// - outgoing_message: The outgoing message that was sent.
    /// - conversation_id: The ID of the conversation that the message was sent to.
    MessageSent(Message, OutgoingMessage, ConversationID),

    /// Gets an attachment object from the attachment store.
    /// Parameters:
    /// - guid: The attachment guid
    /// - reply: Reply of the attachment object, if known.
    GetAttachment(String, Reply<Attachment>),

    /// Downloads an attachment from the server.
    /// Parameters:
    /// - attachment_id: The attachment ID to download
    /// - preview: Whether to download the preview (true) or full attachment (false)
    /// - reply: Reply indicating success or failure
    DownloadAttachment(String, bool, Reply<()>),

    /// Delete all conversations from the database.
    DeleteAllConversations(Reply<()>),

    /// Notifies the daemon that an attachment has been downloaded.
    /// Parameters:
    /// - attachment_id: The attachment ID that was downloaded.
    AttachmentDownloaded(String),

    /// Upload an attachment to the server.
    /// Parameters:
    /// - path: The path to the attachment file
    /// - reply: Reply indicating the upload GUID
    UploadAttachment(PathBuf, Reply<String>),

    /// Notifies the daemon that an attachment has been uploaded.
    /// Parameters:
    /// - upload_id: The upload ID that was uploaded.
    /// - attachment_id: The attachment ID that was uploaded.
    AttachmentUploaded(String, String),
}
