//! Data models for CoinGecko coin response

use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Full coin response from CoinGecko /coins/{id} endpoint
#[derive(Debug, Serialize, Deserialize)]
pub struct CoinResponse {
    pub id: String,
    pub symbol: String,
    pub name: String,
    #[serde(default)]
    pub web_slug: Option<String>,
    #[serde(default)]
    pub asset_platform_id: Option<String>,
    #[serde(default)]
    pub block_time_in_minutes: Option<i32>,
    #[serde(default)]
    pub hashing_algorithm: Option<String>,
    #[serde(default)]
    pub categories: Vec<String>,
    #[serde(default)]
    pub description: Option<Description>,
    #[serde(default)]
    pub links: Option<Links>,
    #[serde(default)]
    pub image: Option<Image>,
    #[serde(default)]
    pub country_origin: Option<String>,
    #[serde(default)]
    pub genesis_date: Option<String>,
    #[serde(default)]
    pub sentiment_votes_up_percentage: Option<f64>,
    #[serde(default)]
    pub sentiment_votes_down_percentage: Option<f64>,
    #[serde(default)]
    pub watchlist_portfolio_users: Option<u64>,
    #[serde(default)]
    pub market_cap_rank: Option<u32>,
    #[serde(default)]
    pub market_data: Option<MarketData>,
    #[serde(default)]
    pub community_data: Option<CommunityData>,
    #[serde(default)]
    pub developer_data: Option<DeveloperData>,
    #[serde(default)]
    pub last_updated: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Description {
    pub en: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Links {
    #[serde(default)]
    pub homepage: Vec<String>,
    #[serde(default)]
    pub whitepaper: Option<String>,
    #[serde(default)]
    pub blockchain_site: Vec<String>,
    #[serde(default)]
    pub official_forum_url: Vec<String>,
    #[serde(default)]
    pub chat_url: Vec<String>,
    #[serde(default)]
    pub announcement_url: Vec<String>,
    #[serde(default)]
    pub twitter_screen_name: Option<String>,
    #[serde(default)]
    pub facebook_username: Option<String>,
    #[serde(default)]
    pub telegram_channel_identifier: Option<String>,
    #[serde(default)]
    pub subreddit_url: Option<String>,
    #[serde(default)]
    pub repos_url: Option<ReposUrl>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ReposUrl {
    #[serde(default)]
    pub github: Vec<String>,
    #[serde(default)]
    pub bitbucket: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Image {
    pub thumb: Option<String>,
    pub small: Option<String>,
    pub large: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct MarketData {
    #[serde(default)]
    pub current_price: HashMap<String, f64>,
    #[serde(default)]
    pub total_value_locked: Option<f64>,
    #[serde(default)]
    pub mcap_to_tvl_ratio: Option<f64>,
    #[serde(default)]
    pub fdv_to_tvl_ratio: Option<f64>,
    #[serde(default)]
    pub ath: HashMap<String, f64>,
    #[serde(default)]
    pub ath_change_percentage: HashMap<String, f64>,
    #[serde(default)]
    pub ath_date: HashMap<String, String>,
    #[serde(default)]
    pub atl: HashMap<String, f64>,
    #[serde(default)]
    pub atl_change_percentage: HashMap<String, f64>,
    #[serde(default)]
    pub atl_date: HashMap<String, String>,
    #[serde(default)]
    pub market_cap: HashMap<String, f64>,
    #[serde(default)]
    pub market_cap_rank: Option<u32>,
    #[serde(default)]
    pub fully_diluted_valuation: HashMap<String, f64>,
    #[serde(default)]
    pub market_cap_fdv_ratio: Option<f64>,
    #[serde(default)]
    pub total_volume: HashMap<String, f64>,
    #[serde(default)]
    pub high_24h: HashMap<String, f64>,
    #[serde(default)]
    pub low_24h: HashMap<String, f64>,
    #[serde(default)]
    pub price_change_24h: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_24h: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_7d: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_14d: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_30d: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_60d: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_200d: Option<f64>,
    #[serde(default)]
    pub price_change_percentage_1y: Option<f64>,
    #[serde(default)]
    pub market_cap_change_24h: Option<f64>,
    #[serde(default)]
    pub market_cap_change_percentage_24h: Option<f64>,
    #[serde(default)]
    pub total_supply: Option<f64>,
    #[serde(default)]
    pub max_supply: Option<f64>,
    #[serde(default)]
    pub circulating_supply: Option<f64>,
    #[serde(default)]
    pub last_updated: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct CommunityData {
    #[serde(default)]
    pub facebook_likes: Option<u64>,
    #[serde(default)]
    pub twitter_followers: Option<u64>,
    #[serde(default)]
    pub reddit_average_posts_48h: Option<f64>,
    #[serde(default)]
    pub reddit_average_comments_48h: Option<f64>,
    #[serde(default)]
    pub reddit_subscribers: Option<u64>,
    #[serde(default)]
    pub reddit_accounts_active_48h: Option<u64>,
    #[serde(default)]
    pub telegram_channel_user_count: Option<u64>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct DeveloperData {
    #[serde(default)]
    pub forks: Option<u32>,
    #[serde(default)]
    pub stars: Option<u32>,
    #[serde(default)]
    pub subscribers: Option<u32>,
    #[serde(default)]
    pub total_issues: Option<u32>,
    #[serde(default)]
    pub closed_issues: Option<u32>,
    #[serde(default)]
    pub pull_requests_merged: Option<u32>,
    #[serde(default)]
    pub pull_request_contributors: Option<u32>,
    #[serde(default)]
    pub code_additions_deletions_4_weeks: Option<CodeAdditionsDeletions>,
    #[serde(default)]
    pub commit_count_4_weeks: Option<u32>,
    #[serde(default)]
    pub last_4_weeks_commit_activity_series: Vec<u32>,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct CodeAdditionsDeletions {
    pub additions: Option<i64>,
    pub deletions: Option<i64>,
}
