// src/corporate/types.rs
use std::collections::HashMap;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CompanyEvent {
    pub ticker: String,
    pub date: String,                    // YYYY-MM-DD
    pub time: String,                    // "AMC", "BMO", "TAS", or ""
    pub period: String,                  // "Q1 2025", "FY 2024"
    pub eps_forecast: Option<f64>,
    pub eps_actual: Option<f64>,
    pub revenue_forecast: Option<f64>,
    pub revenue_actual: Option<f64>,
    pub surprise_pct: Option<f64>,       // (actual - forecast) / |forecast|
    pub source: String,                  // "Yahoo"
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompanyPrice {
    pub ticker: String,
    pub date: String,                    // YYYY-MM-DD
    pub time: String,                    // HH:MM:SS for intraday, "" for daily
    pub open: f64,
    pub high: f64,
    pub low: f64,
    pub close: f64,
    pub adj_close: f64,
    pub volume: u64,
    pub currency: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompanyEventChange {
    pub ticker: String,
    pub date: String,
    pub field_changed: String,           // "time", "eps_forecast", "eps_actual", "new_event"
    pub old_value: String,
    pub new_value: String,
    pub detected_at: String,
}

/// Figi Info based on API calls [https://www.openfigi.com/]
/// # Attributes
/// isin: ISIN belonging to this legal entity from lei
/// 
/// # Comments
/// Use Mapping the Object List onto Figi Properties
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FigiInfo {
    pub isin: String,
    pub figi: String,
    pub name: String,
    pub ticker: String,
    pub exch_code: String,
    #[serde(rename = "compositeFIGI")]
    pub composite_figi: String,
    #[serde(rename = "securityType")]
    pub security_type: String,
    #[serde(rename = "marketSector")]
    pub market_sector: String,
    #[serde(rename = "shareClassFIGI")]
    pub share_class_figi: String,
    #[serde(rename = "securityType2")]
    pub security_type2: String,
    #[serde(rename = "securityDescription")]
    pub security_description: String,
}

/// Company Info
/// # Attributes
/// * Name as primary key (for one institution) -> might have to changed when first FigiInfo is coming in
/// * ISIN as the most liquid / preferred traded security (used for fallback)
/// * securities: Grouped by ISIN, filtered for Common Stock only
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompanyInfo{
    pub name: String,
    pub primary_isin: String,
    pub securities: HashMap<String, Vec<FigiInfo>>, // ISIN -> Vec<FigiInfo>
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YahooCompanyDetails {
    pub ticker: String,
    pub sector: Option<String>,
    pub exchange: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompanyCrossPlatformInfo {
    pub name: String,
    pub isin_tickers_map: HashMap<String, Vec<String>>, // ISIN -> Tickers
    pub sector: Option<String>,
    pub exchange: Option<String>,
}

/// Warrant Info
/// 
/// Information for Warrant securities fetched out of Name in FigiInfo         
/// example1: "name": "VONTOBE-PW26 LEONARDO SPA",
/// issued by VONTOBEL Put Warrant for underlying company LEONARDO SPA
/// example2: "BAYER H-CW25 L'OREAL",
/// other formats like only on company instead of two, underlying and issuing company are the same, leave issuer_company_name NULL
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WarrantInfo {
    pub underlying_company_name: String, // key in CompanyInfo, key for WarrantInfo
    pub issuer_company_name: Option<String>, // key in CompanyInfo
    pub warrant_type: String, // "put" or "call"
    pub warrants: HashMap<String, Vec<FigiInfo>>, // ISIN -> Vec<FigiInfo> (grouped by ISIN)
}

/// Option Info
/// 
/// Information for Option securities fetched out of Name in FigiInfo         
/// example1: "name": "December 25 Calls on ALPHA GA",
/// issued by NULL Call Option for underlying company ALPHA GA
/// other formats like only on company instead of two, underlying and issuing company are the same, leave issuer_company_name NULL
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptionInfo {
    pub underlying_company_name: String, // key in CompanyInfo, key for OptionInfo
    pub issuer_company_name: Option<String>, // key in CompanyInfo
    pub option_type: String, // "put" or "call"
    pub options: HashMap<String, Vec<FigiInfo>>, // ISIN -> Vec<FigiInfo> (grouped by ISIN)
}

/// Bond parsed details from ticker/description
/// 
/// Parses bond information from ticker format:
/// Corporate: "WTFC 4.3 01/12/26 0003"
/// Government: "SLOVAK 1.5225 05/10/28 4Y"
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BondDetails {
    pub coupon_rate: Option<f64>,        // 4.3, 1.5225
    pub maturity_date: Option<String>,   // "2026-01-12", "2028-05-10"
    pub is_floating: bool,               // true if "Float" in description
    pub is_zero_coupon: bool,            // true if coupon is 0
    pub tenor_years: Option<u32>,        // Parsed from maturity or inferred
    pub series_identifier: Option<String>, // "0003", "4Y", "144A", "REGS", etc.
}

/// Corporate Bond Info
/// 
/// Information for corporate bonds grouped by issuer
/// Example: "name": "LIBERTYVILLE BK & TRUST"
/// ticker: "WTFC 4.3 01/12/26 0003"
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CorporateBondInfo {
    pub issuer_name: String,             // key - company name issuing the bond
    pub bonds: HashMap<String, Vec<FigiInfo>>, // ISIN -> Vec<FigiInfo> (grouped by ISIN)
    #[serde(skip_serializing_if = "HashMap::is_empty", default)]
    pub bond_details: HashMap<String, BondDetails>, // ISIN -> parsed bond details
}

/// Government Bond Info
/// 
/// Information for government bonds grouped by issuer (country/municipality)
/// Example: "name": "SLOVAK REPUBLIC"
/// ticker: "SLOVAK 1.5225 05/10/28 4Y"
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GovernmentBondInfo {
    pub issuer_name: String,             // key - government entity name
    pub issuer_type: String,             // "sovereign", "municipal", "state", "province", etc.
    pub bonds: HashMap<String, Vec<FigiInfo>>, // ISIN -> Vec<FigiInfo> (grouped by ISIN)
    #[serde(skip_serializing_if = "HashMap::is_empty", default)]
    pub bond_details: HashMap<String, BondDetails>, // ISIN -> parsed bond details
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AvailableExchange {
    pub exchange_mic: String,
    pub ticker: String,
    pub has_daily: bool,
    pub has_5min: bool,
    pub last_successful_fetch: Option<String>, // YYYY-MM-DD
    #[serde(default)]
    pub currency: String,
    #[serde(default)]
    pub discovered_at: Option<String>,   // When this exchange was first discovered
    #[serde(default)]
    pub fetch_count: u32,                // How many times successfully fetched
}