use owo_colors::OwoColorize;
use rust_decimal::Decimal;

use crate::commands::portfolio::PortfolioSnapshot;
use crate::output::OutputFormat;
use crate::style::Styles;

pub fn print_portfolio(snapshot: &PortfolioSnapshot, format: OutputFormat) {
    match format {
        OutputFormat::Json => super::print_json(snapshot),
        OutputFormat::Table => print_table(snapshot),
    }
}

fn print_table(snapshot: &PortfolioSnapshot) {
    let s = Styles::new();

    // Account Health
    println!("{}", "Account Health".style(s.cyan));
    println!(
        "  Net Equity:              {}",
        format_decimal(&snapshot.account_health.net_equity)
    );
    if let Some(mf) = snapshot.account_health.margin_fraction {
        println!("  Margin Fraction:         {}", mf);
    }
    if let Some(util) = snapshot.account_health.margin_utilization_pct {
        let util_str = format!("{:.2}%", util);
        let colored = if util > Decimal::from(80) {
            format!("{}", util_str.style(s.red))
        } else if util > Decimal::from(50) {
            format!("{}", util_str.style(s.yellow))
        } else {
            format!("{}", util_str.style(s.green))
        };
        println!("  Margin Utilization:      {colored}");
    }
    if let Some(dist) = snapshot.account_health.distance_to_liquidation_pct {
        let dist_str = format!("{:.2}%", dist);
        let colored = if dist < Decimal::from(20) {
            format!("{}", dist_str.style(s.red))
        } else if dist < Decimal::from(50) {
            format!("{}", dist_str.style(s.yellow))
        } else {
            format!("{}", dist_str.style(s.green))
        };
        println!("  Distance to Liquidation: {colored}");
    }
    println!();

    // PnL
    println!("{}", "PnL".style(s.cyan));
    println!(
        "  Unrealized Total:        {}",
        format_pnl_value(snapshot.pnl.unrealized_total, &s)
    );
    println!(
        "  Funding Accrued:         {}",
        format_pnl_value(snapshot.pnl.funding_accrued, &s)
    );
    println!();

    // Collateral
    println!("{}", "Collateral".style(s.cyan));
    println!(
        "  Total Value:             {}",
        format_decimal(&snapshot.collateral.total_value)
    );
    println!(
        "  Weighted Value:          {}",
        format_decimal(&snapshot.collateral.weighted_value)
    );
    if let Some(ref breakdown) = snapshot.collateral.breakdown {
        println!();
        println!("  {}", "Breakdown".style(s.bold));
        println!(
            "    {:<10} {:>14} {:>8} {:>14}",
            "SYMBOL", "NOTIONAL", "WEIGHT", "VALUE"
        );
        for item in breakdown {
            println!(
                "    {:<10} {:>14} {:>8} {:>14}",
                item.symbol, item.notional, item.weight, item.value
            );
        }
    }
    println!();

    // Positions
    println!("{}", "Positions".style(s.cyan));
    if snapshot.positions.is_empty() {
        println!("  No open positions.");
    } else {
        println!(
            "  {:<20} {:>12} {:>14} {:>14} {:>14} {:>14}",
            "SYMBOL", "NET QTY", "ENTRY", "MARK", "UNREAL PNL", "LIQ PRICE"
        );
        for p in &snapshot.positions {
            let pnl_display = format_pnl_str(&p.unrealized_pnl, &s);
            println!(
                "  {:<20} {:>12} {:>14} {:>14} {:>14} {:>14}",
                p.symbol,
                p.net_quantity,
                p.entry_price,
                p.mark_price,
                pnl_display,
                p.liquidation_price
            );
        }
    }
    println!();

    // Open Orders
    println!("{}", "Open Orders".style(s.cyan));
    println!("  Count:                   {}", snapshot.open_orders.count);
    println!(
        "  Notional Locked:         {}",
        format_decimal(&snapshot.open_orders.notional_locked)
    );
    println!();

    // Lending
    if let Some(ref lending) = snapshot.lending {
        println!("{}", "Lending".style(s.cyan));
        println!(
            "  Total Lent Value:        {}",
            format_decimal(&lending.total_lent_value)
        );
        println!(
            "  Cumulative Interest:     {}",
            format_pnl_value(lending.daily_income, &s)
        );
        println!();
    }

    println!(
        "{}",
        format!("Snapshot at {}", snapshot.timestamp).style(s.dim)
    );
}

fn format_decimal(d: &Decimal) -> String {
    d.to_string()
}

fn format_pnl_value(value: Decimal, s: &Styles) -> String {
    if value < Decimal::ZERO {
        format!("{}", value.style(s.red))
    } else if value > Decimal::ZERO {
        format!("{}", value.style(s.green))
    } else {
        value.to_string()
    }
}

fn format_pnl_str(value: &str, s: &Styles) -> String {
    if value.starts_with('-') {
        format!("{}", value.style(s.red))
    } else if value.parse::<f64>().is_ok_and(|v| v == 0.0) {
        value.to_string()
    } else {
        format!("{}", value.style(s.green))
    }
}
