use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

// =============================================================================
// GET USER PROFILE
// =============================================================================

/// Response from /api/profiles/{handle} endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct UserProfileResponse {
    pub user_id: Uuid,

    pub handle: String,

    pub display_name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_image_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub bio: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub banner_image_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub follower_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub following_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub clip_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub playlist_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_followed: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_self: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_blocked: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub clips: Option<Vec<ProfileClip>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub playlists: Option<Vec<ProfilePlaylist>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_clips: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub created_at: Option<DateTime<Utc>>,
}

/// Clip in user profile
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ProfileClip {
    pub id: Uuid,

    pub title: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub image_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_url: Option<String>,

    pub play_count: i32,

    pub upvote_count: i32,

    pub created_at: DateTime<Utc>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_liked: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub comment_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<String>,
}

/// Playlist in user profile
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ProfilePlaylist {
    pub id: String,

    pub name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub image_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub playlist_clips_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub upvote_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub play_count: Option<i32>,
}

// =============================================================================
// GET RECENT CLIPS
// =============================================================================

/// Response from /api/profiles/{handle}/recent_clips endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RecentClipsResponse {
    pub clips: Vec<ProfileClip>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub user_id: Option<Uuid>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub display_name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub handle: Option<String>,
}

// =============================================================================
// GET FOLLOWERS
// =============================================================================

/// Response from /api/profiles/{handle}/followers endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FollowersResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub followers: Option<Vec<FollowerUser>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub profiles: Option<Vec<FollowerUser>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page_size: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub has_more: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub user_id: Option<Uuid>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub handle: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub current_page: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub num_total_profiles: Option<i32>,
}

/// Follower user item
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FollowerUser {
    pub user_id: Uuid,

    pub handle: String,

    pub display_name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_image_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub bio: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub follower_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_followed: Option<bool>,
}

// =============================================================================
// GET FOLLOWING
// =============================================================================

/// Response from /api/profiles/{handle}/following endpoint
pub type FollowingResponse = FollowersResponse;

// =============================================================================
// GET TOP CLIPS
// =============================================================================

/// Response from /api/profiles/top_clips endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TopClipsResponse {
    pub clips: Vec<TopClip>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,
}

/// Top clip (ranked by upvotes/plays)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TopClip {
    pub id: Uuid,

    pub title: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub image_url: Option<String>,

    pub play_count: i32,

    pub upvote_count: i32,

    pub created_at: DateTime<Utc>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub rank: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub allow_comments: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub entity_type: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub video_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub audio_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub image_large_url: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub major_model_version: Option<String>,
}

// =============================================================================
// GET PINNED CLIPS
// =============================================================================

/// Response from /api/profiles/pinned-clips endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PinnedClipsResponse {
    pub clips: Vec<ProfileClip>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,
}

// =============================================================================
// GET REMIXES INSPIRED
// =============================================================================

/// Response from /api/profiles/{handle}/remixes-inspired endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RemixesInspiredResponse {
    pub remixes: Vec<InspiredRemix>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page_size: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub has_more: Option<bool>,
}

/// Remix inspired by original user's clip
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InspiredRemix {
    pub remix_clip_id: Uuid,

    pub remix_title: String,

    pub original_clip_id: Uuid,

    pub original_title: String,

    pub remix_creator_handle: String,

    pub remix_creator_display_name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub remix_created_at: Option<DateTime<Utc>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub remix_upvote_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub remix_play_count: Option<i32>,
}

// =============================================================================
// GET BLOCKED USERS
// =============================================================================

/// Response from /api/profiles/blocked_users endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BlockedUsersResponse {
    pub blocked_users: Vec<FollowerUser>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub page_size: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub has_more: Option<bool>,
}

// =============================================================================
// GET LISTEN HISTORY
// =============================================================================

/// Response from /api/profiles/{handle}/listen-history endpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListenHistoryResponse {
    pub history: Vec<ListenHistoryItem>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub has_more: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub total_count: Option<i32>,
}

/// Listen history entry
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ListenHistoryItem {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub clip_id: Option<Uuid>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub title: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub creator_handle: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub creator_display_name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub image_url: Option<String>,

    pub listened_at: DateTime<Utc>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub duration_seconds: Option<f32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub play_count: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub content: Option<serde_json::Value>,
}
