use crate::core::{Problem, localized, normalize_ui_language, ui_text};
use ratatui::{
    style::{Color, Modifier, Style},
    text::{Line, Span, Text},
};

pub(super) fn render(problem: &Problem, ui_language: &str, light: bool) -> Text<'static> {
    let lang = normalize_ui_language(ui_language);
    let title_style = if light {
        Style::default()
            .fg(Color::Blue)
            .add_modifier(Modifier::BOLD)
    } else {
        Style::default()
            .fg(Color::Yellow)
            .add_modifier(Modifier::BOLD)
    };
    let section_style = if light {
        Style::default()
            .fg(Color::Magenta)
            .add_modifier(Modifier::BOLD)
    } else {
        Style::default()
            .fg(Color::Cyan)
            .add_modifier(Modifier::BOLD)
    };
    let body_style = if light {
        Style::default().fg(Color::Black)
    } else {
        Style::default().fg(Color::Rgb(229, 231, 235))
    };
    let meta_style = if light {
        Style::default().fg(Color::Rgb(75, 85, 99))
    } else {
        Style::default().fg(Color::Rgb(156, 163, 175))
    };
    let code_style = if light {
        Style::default()
            .fg(Color::Black)
            .bg(Color::Rgb(229, 231, 235))
    } else {
        Style::default()
            .fg(Color::Rgb(243, 244, 246))
            .bg(Color::Rgb(31, 41, 55))
    };
    let number = problem
        .id
        .split_once('-')
        .map(|(number, _)| number)
        .unwrap_or(&problem.id);
    let mut lines = vec![
        Line::from(Span::styled(
            format!("{number}. {}", localized(&problem.title, &lang)),
            title_style,
        )),
        Line::from(Span::styled(
            format!(
                "{}: {}    {}: {}",
                ui_text(&lang, "difficulty"),
                problem.difficulty,
                ui_text(&lang, "topics"),
                problem.topics.join(", ")
            ),
            meta_style,
        )),
    ];
    lines.push(Line::default());
    for line in localized(&problem.statement, &lang).trim_end().lines() {
        lines.push(Line::from(Span::styled(line.to_string(), body_style)));
    }
    push_problem_section(
        &mut lines,
        ui_text(&lang, "input"),
        &localized(&problem.input, &lang),
        section_style,
        body_style,
    );
    push_problem_section(
        &mut lines,
        ui_text(&lang, "output"),
        &localized(&problem.output, &lang),
        section_style,
        body_style,
    );
    lines.push(Line::default());
    lines.push(Line::from(Span::styled(
        ui_text(&lang, "examples").to_string(),
        section_style,
    )));
    for (index, case) in problem.examples.iter().enumerate() {
        lines.push(Line::from(Span::styled(
            format!("  {} {}", ui_text(&lang, "example"), index + 1),
            meta_style.add_modifier(Modifier::BOLD),
        )));
        lines.push(Line::from(Span::styled(
            format!("    {}", ui_text(&lang, "input")),
            meta_style,
        )));
        push_code_lines(&mut lines, &case.input, code_style);
        lines.push(Line::from(Span::styled(
            format!("    {}", ui_text(&lang, "output")),
            meta_style,
        )));
        push_code_lines(&mut lines, &case.output, code_style);
    }
    Text::from(lines)
}

fn push_problem_section(
    lines: &mut Vec<Line<'static>>,
    title: &str,
    body: &str,
    section_style: Style,
    body_style: Style,
) {
    lines.push(Line::default());
    lines.push(Line::from(Span::styled(title.to_string(), section_style)));
    for line in body.trim_end().lines() {
        lines.push(Line::from(Span::styled(format!("  {line}"), body_style)));
    }
}

fn push_code_lines(lines: &mut Vec<Line<'static>>, body: &str, code_style: Style) {
    let body = body.trim_end();
    if body.is_empty() {
        lines.push(Line::from(vec![
            Span::raw("      "),
            Span::styled("<empty>".to_string(), code_style),
        ]));
        return;
    }
    for line in body.lines() {
        lines.push(Line::from(vec![
            Span::raw("      "),
            Span::styled(line.to_string(), code_style),
        ]));
    }
}
