//! Tests against real-world-shaped FLEX fixtures adapted from the MIT-licensed
//! `robcohen/ibflex2` project (anonymized). These exercise edge cases that the
//! original synthetic fixtures did not: legacy comma date/time separators,
//! stock-grant activity, and crypto OTC transfers with sentinel values.

use ib_flex::parse_activity_flex;
use ib_flex::types::TransferType;
use rust_decimal::Decimal;
use std::str::FromStr;

#[test]
fn wild_legacy_comma_separator() {
    // Older statements separate date and time with ", " instead of ";".
    let xml = include_str!("fixtures/wild_legacy_separator.xml");
    let statement = parse_activity_flex(xml).expect("legacy-separator statement should parse");

    // whenGenerated is kept raw (comma separator and all), not dropped.
    assert!(statement
        .when_generated
        .as_deref()
        .unwrap_or("")
        .contains("2017-02-01"));

    let cash = &statement.cash_transactions.items;
    assert_eq!(cash.len(), 1);
    assert_eq!(cash[0].amount, Some(Decimal::from_str("5000.00").unwrap()));
    assert_eq!(cash[0].description.as_deref(), Some("LEGACY DEPOSIT"));
}

#[test]
fn wild_stock_grant_activity() {
    // StockGrantActivity was previously parsed-and-dropped (IgnoredSection).
    let xml = include_str!("fixtures/wild_stock_grant.xml");
    let statement = parse_activity_flex(xml).expect("stock-grant statement should parse");

    let grants = &statement.stock_grant_activities.items;
    assert_eq!(grants.len(), 1, "stock grant activity should be captured");
    let g = &grants[0];
    assert_eq!(g.symbol.as_deref(), Some("IBKR"));
    assert_eq!(g.vesting_date, date_opt("2026-06-12"));
    assert_eq!(g.quantity, Some(Decimal::from_str("2.6454").unwrap()));
    assert_eq!(g.value, Some(Decimal::from_str("541.01").unwrap()));
}

#[test]
fn wild_crypto_otc_transfer() {
    // Crypto OTC transfer: new TransferType::Otc, CRYPTO asset class, and a
    // "--" sentinel in the `company` field (must become None, not error).
    let xml = include_str!("fixtures/wild_crypto_transfer.xml");
    let statement = parse_activity_flex(xml).expect("crypto-transfer statement should parse");

    let transfers = &statement.transfers.items;
    assert_eq!(transfers.len(), 1);
    let t = &transfers[0];
    assert_eq!(t.transfer_type, Some(TransferType::OTC));
    assert_eq!(t.symbol.as_deref(), Some("BTC.USD-PAXOS"));
    // `company="--"` is a null sentinel and should deserialize to None.
    assert_eq!(t.company, None);
}

// Small helper to keep date assertions readable.
fn date_opt(s: &str) -> Option<chrono::NaiveDate> {
    Some(chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d").unwrap())
}
