use serde::{Deserialize, Serialize};
use specta::Type;
use tauri_specta::Event;

use crate::{
    models::{
        app_data::UserData,
        app_state::AppState,
        event_payloads::{
            FriendActiveDollChangedPayload, FriendDisconnectedPayload,
            FriendRequestAcceptedPayload, FriendRequestDeniedPayload, FriendRequestReceivedPayload,
            FriendUserStatusPayload, UnfriendedPayload, UserStatusPayload,
        },
        interaction::{InteractionDeliveryFailedDto, InteractionPayloadDto},
    },
    services::{friends::FriendActiveDollSpritesDto, neko_positions::NekoPositionsDto},
};

#[derive(Debug, Clone, Serialize, Deserialize, Type)]
#[serde(rename_all = "snake_case")]
pub enum AuthFlowStatus {
    Started,
    Succeeded,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
pub struct AuthFlowUpdatedPayload {
    pub provider: String,
    pub status: AuthFlowStatus,
    pub message: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "scene-interactive")]
pub struct SceneInteractiveChanged(pub bool);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "app-data-refreshed")]
pub struct AppDataRefreshed(pub UserData);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "app-state-changed")]
pub struct AppStateChanged(pub AppState);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "active-doll-sprite-changed")]
pub struct ActiveDollSpriteChanged(pub Option<String>);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "set-interaction-overlay")]
pub struct SetInteractionOverlay(pub bool);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "edit-doll")]
pub struct EditDoll(pub String);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "create-doll")]
pub struct CreateDoll;

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "user-status-changed")]
pub struct UserStatusChanged(pub UserStatusPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "neko-positions")]
pub struct NekoPositionsUpdated(pub NekoPositionsDto);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-disconnected")]
pub struct FriendDisconnected(pub FriendDisconnectedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-active-doll-changed")]
pub struct FriendActiveDollChanged(pub FriendActiveDollChangedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-active-doll-sprites-updated")]
pub struct FriendActiveDollSpritesUpdated(pub FriendActiveDollSpritesDto);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-user-status")]
pub struct FriendUserStatusChanged(pub FriendUserStatusPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "interaction-received")]
pub struct InteractionReceived(pub InteractionPayloadDto);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "interaction-delivery-failed")]
pub struct InteractionDeliveryFailed(pub InteractionDeliveryFailedDto);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-request-received")]
pub struct FriendRequestReceived(pub FriendRequestReceivedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-request-accepted")]
pub struct FriendRequestAccepted(pub FriendRequestAcceptedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "friend-request-denied")]
pub struct FriendRequestDenied(pub FriendRequestDeniedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "unfriended")]
pub struct Unfriended(pub UnfriendedPayload);

#[derive(Debug, Clone, Serialize, Deserialize, Type, Event)]
#[tauri_specta(event_name = "auth-flow-updated")]
pub struct AuthFlowUpdated(pub AuthFlowUpdatedPayload);
