#![allow(clippy::indexing_slicing)] // ratatui Layout::split indices match constraints
//! Overview cockpit -- four-quadrant summary dashboard.
//!
//! Top-left:  Service health list
//! Top-right: CPU / RAM / GPU gauges
//! Bottom-left:  Training summary table
//! Bottom-right: Portfolio summary

use ratatui::Frame;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Gauge, List, ListItem, Row, Table};

use crate::tui::cockpit::Cockpit;
use crate::tui::state::AppState;
use crate::tui::theme;

pub struct OverviewCockpit;

impl Cockpit for OverviewCockpit {
    fn name(&self) -> &str {
        "Overview"
    }

    fn render(&self, frame: &mut Frame, area: Rect, state: &AppState) {
        let rows = Layout::default()
            .direction(Direction::Vertical)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(area);

        let top = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(rows[0]);

        let bottom = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Percentage(30),
                Constraint::Percentage(30),
                Constraint::Percentage(40),
            ])
            .split(rows[1]);

        render_services(frame, top[0], state);
        render_resources(frame, top[1], state);
        render_training_summary(frame, bottom[0], state);
        render_portfolio(frame, bottom[1], state);
        render_pods_summary(frame, bottom[2], state);
    }
}

// ---------------------------------------------------------------------------
// Quadrant renderers
// ---------------------------------------------------------------------------

fn render_services(frame: &mut Frame, area: Rect, state: &AppState) {
    let items: Vec<ListItem> = state
        .services
        .iter()
        .map(|s| {
            let dot = if s.healthy { "\u{25CF}" } else { "\u{25CB}" };
            let style = theme::status_style(s.healthy);
            ListItem::new(Line::from(vec![
                Span::styled(format!("{dot} "), style),
                Span::styled(&s.name, Style::default().fg(theme::TEXT)),
                Span::styled(format!("  {}", s.uptime), theme::muted_style()),
            ]))
        })
        .collect();

    let list = List::new(items).block(theme::block(" Services "));
    frame.render_widget(list, area);
}

fn render_resources(frame: &mut Frame, area: Rect, state: &AppState) {
    let block = theme::block(" Resources ");
    let inner = block.inner(area);
    frame.render_widget(block, area);

    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(2),
            Constraint::Length(2),
            Constraint::Length(2),
            Constraint::Min(0),
        ])
        .split(inner);

    // CPU gauge
    let cpu_pct = state.system_resources.cpu_usage_pct / 100.0;
    let cpu_label = format!("CPU  {:.1}%", state.system_resources.cpu_usage_pct);
    let cpu_gauge = Gauge::default()
        .gauge_style(Style::default().fg(theme::SECONDARY))
        .label(cpu_label)
        .ratio(cpu_pct.clamp(0.0, 1.0));
    frame.render_widget(cpu_gauge, chunks[0]);

    // RAM gauge
    let ram_pct = if state.system_resources.ram_total_gb > 0.0 {
        state.system_resources.ram_used_gb / state.system_resources.ram_total_gb
    } else {
        0.0
    };
    let ram_label = format!(
        "RAM  {:.1}/{:.0} GB",
        state.system_resources.ram_used_gb, state.system_resources.ram_total_gb
    );
    let ram_gauge = Gauge::default()
        .gauge_style(Style::default().fg(theme::PRIMARY))
        .label(ram_label)
        .ratio(ram_pct.clamp(0.0, 1.0));
    frame.render_widget(ram_gauge, chunks[1]);

    // GPU gauge
    let gpu_pct = state.gpu.utilization / 100.0;
    let gpu_label = format!("GPU  {:.1}%  {}", state.gpu.utilization, state.gpu.name);
    let gpu_gauge = Gauge::default()
        .gauge_style(Style::default().fg(theme::HIGHLIGHT))
        .label(gpu_label)
        .ratio(gpu_pct.clamp(0.0, 1.0));
    frame.render_widget(gpu_gauge, chunks[2]);
}

fn render_training_summary(frame: &mut Frame, area: Rect, state: &AppState) {
    // When training sessions are active, show training metrics.
    // When idle, show ML model statuses instead.
    if state.training_sessions.is_empty() && !state.model_statuses.is_empty() {
        render_model_statuses(frame, area, state);
        return;
    }

    let header = Row::new(vec!["Model", "Epoch", "Loss", "Sharpe"])
        .style(theme::header_style());

    let rows: Vec<Row> = state
        .training_sessions
        .iter()
        .map(|s| {
            Row::new(vec![
                s.model.clone(),
                s.epoch.to_string(),
                format!("{:.4}", s.loss),
                format!("{:.2}", s.sharpe),
            ])
            .style(Style::default().fg(theme::TEXT))
        })
        .collect();

    let table = Table::new(
        rows,
        [
            Constraint::Length(10),
            Constraint::Length(10),
            Constraint::Length(10),
            Constraint::Length(10),
        ],
    )
    .header(header)
    .block(theme::block(" Training "));

    frame.render_widget(table, area);
}

fn render_model_statuses(frame: &mut Frame, area: Rect, state: &AppState) {
    let header = Row::new(vec!["Model", "State", "Health", "Last Pred"])
        .style(theme::header_style());

    let rows: Vec<Row> = state
        .model_statuses
        .iter()
        .map(|m| {
            let state_style = match m.state.as_str() {
                "ACTIVE" | "READY" => Style::default().fg(theme::SUCCESS),
                "ERROR" | "OFFLINE" => Style::default().fg(theme::ERROR),
                "LOADING" | "TRAINING" => Style::default().fg(theme::WARNING),
                _ => Style::default().fg(theme::TEXT),
            };

            let health_style = match m.health.as_str() {
                "OK" => Style::default().fg(theme::SUCCESS),
                "DEGRADED" => Style::default().fg(theme::WARNING),
                "UNHEALTHY" | "CRITICAL" => Style::default().fg(theme::ERROR),
                _ => Style::default().fg(theme::TEXT),
            };

            Row::new(vec![
                Span::styled(m.model_name.clone(), Style::default().fg(theme::TEXT)),
                Span::styled(m.state.clone(), state_style),
                Span::styled(m.health.clone(), health_style),
                Span::styled(m.last_prediction.clone(), theme::muted_style()),
            ])
        })
        .collect();

    let table = Table::new(
        rows,
        [
            Constraint::Length(10),
            Constraint::Length(10),
            Constraint::Length(10),
            Constraint::Length(10),
        ],
    )
    .header(header)
    .block(theme::block(" ML Models "));

    frame.render_widget(table, area);
}

fn render_portfolio(frame: &mut Frame, area: Rect, state: &AppState) {
    let block = theme::block(" Portfolio ");
    let inner = block.inner(area);
    frame.render_widget(block, area);

    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Length(5), Constraint::Min(0)])
        .split(inner);

    // Account summary lines
    let pnl_style = if state.account.daily_pnl >= 0.0 {
        theme::status_style(true)
    } else {
        theme::status_style(false)
    };

    let summary_items = vec![
        ListItem::new(Line::from(vec![
            Span::styled("Equity    ", theme::muted_style()),
            Span::styled(
                theme::format_usd(state.account.equity),
                Style::default().fg(theme::TEXT),
            ),
        ])),
        ListItem::new(Line::from(vec![
            Span::styled("Cash      ", theme::muted_style()),
            Span::styled(
                theme::format_usd(state.account.cash),
                Style::default().fg(theme::TEXT),
            ),
        ])),
        ListItem::new(Line::from(vec![
            Span::styled("Daily P&L ", theme::muted_style()),
            Span::styled(theme::format_usd_signed(state.account.daily_pnl), pnl_style),
        ])),
        ListItem::new(Line::from(vec![
            Span::styled("Positions ", theme::muted_style()),
            Span::styled(
                format!("{}", state.positions.len()),
                Style::default().fg(theme::TEXT),
            ),
        ])),
    ];
    let summary = List::new(summary_items);
    frame.render_widget(summary, chunks[0]);
}

fn render_pods_summary(frame: &mut Frame, area: Rect, state: &AppState) {
    if state.pods.is_empty() {
        let msg = ratatui::widgets::Paragraph::new(
            Line::from(Span::styled("No pod data", theme::muted_style())),
        )
        .block(theme::block(" Pods "));
        frame.render_widget(msg, area);
        return;
    }

    // Compact: one row per service group (no sub-pod expansion).
    let header = Row::new(vec!["Service", "Ready", "Status"])
        .style(theme::header_style());

    let rows: Vec<Row<'_>> = state
        .pods
        .iter()
        .map(|g| {
            let ready_str = format!("{}/{}", g.ready_count, g.total_count);
            let (status_text, status_style) = if g.ready_count == g.total_count
                && g.total_count > 0
            {
                ("Running", Style::default().fg(theme::SUCCESS))
            } else if g.ready_count > 0 {
                ("Degraded", Style::default().fg(theme::WARNING))
            } else {
                ("Down", Style::default().fg(theme::ERROR))
            };

            Row::new(vec![
                Span::styled(
                    g.service.clone(),
                    Style::default()
                        .fg(theme::TEXT)
                        .add_modifier(Modifier::BOLD),
                ),
                Span::styled(ready_str, Style::default().fg(theme::TEXT)),
                Span::styled(status_text.to_owned(), status_style),
            ])
        })
        .collect();

    let table = Table::new(
        rows,
        [
            Constraint::Length(14),
            Constraint::Length(6),
            Constraint::Min(8),
        ],
    )
    .header(header)
    .block(theme::block(" Pods "));

    frame.render_widget(table, area);
}
