//! Condensed timeline output - collapsed sequences as readable log

use crate::{LogAnalyzer, LogGroup, SequencePattern};
use anyhow::Result;

/// Generate condensed timeline log showing sequences collapsed
pub fn generate_condensed_timeline(analyzer: &LogAnalyzer, min_reps: usize) -> Result<String> {
	let mut output = String::new();

	// Header
	output.push_str("# CONDENSED TIMELINE (sequences with >= ");
	output.push_str(&min_reps.to_string());
	output.push_str(" repetitions collapsed)\n");
	output.push_str("# Generated by log-analyzer\n");
	output.push_str("# Format: [COUNT×] timestamp module: message\n\n");

	let groups = analyzer.groups();
	let sequences = analyzer.sequences();
	let templates = analyzer.templates();

	// Track which groups are part of sequences
	let mut groups_in_sequences = std::collections::HashSet::new();
	for seq in sequences {
		if seq.repetitions >= min_reps {
			for &idx in &seq.group_indices {
				groups_in_sequences.insert(idx);
			}
		}
	}

	// Process sequences first (chronologically)
	let mut processed_sequences = Vec::new();
	for seq in sequences {
		if seq.repetitions >= min_reps {
			processed_sequences.push(seq);
		}
	}
	processed_sequences.sort_by_key(|s| s.group_indices.first().copied().unwrap_or(0));

	let mut current_group_idx = 0;
	let mut seq_iter = processed_sequences.iter().peekable();

	while current_group_idx < groups.len() {
		// Check if current position starts a sequence
		if let Some(seq) = seq_iter.peek() {
			if seq.group_indices.first().copied().unwrap_or(0) == current_group_idx {
				// Render sequence
				render_sequence(seq, groups, templates, &mut output)?;

				// Skip groups that are part of this sequence
				current_group_idx += seq.group_indices.len();
				seq_iter.next();
				continue;
			}
		}

		// Not part of sequence - render individual group
		if !groups_in_sequences.contains(&current_group_idx) {
			render_group(&groups[current_group_idx], templates, &mut output)?;
		}

		current_group_idx += 1;
	}

	Ok(output)
}

fn render_sequence(
	seq: &SequencePattern,
	groups: &[LogGroup],
	templates: &[crate::Template],
	output: &mut String,
) -> Result<()> {
	let first_idx = seq.group_indices.first().copied().unwrap_or(0);
	let last_idx = seq.group_indices.last().copied().unwrap_or(0);

	let first_group = &groups[first_idx];
	let last_group = &groups[last_idx];

	let duration_ms = last_group
		.end_time
		.signed_duration_since(first_group.start_time)
		.num_milliseconds();

	// Sequence header
	output.push_str(&format!(
		"\n[{}× SEQUENCE] {} → {} ({} steps, {}ms total)\n",
		seq.repetitions,
		first_group.start_time.format("%H:%M:%S%.3f"),
		last_group.end_time.format("%H:%M:%S%.3f"),
		seq.template_sequence.len(),
		duration_ms
	));

	// Show each step in the sequence
	for (i, &template_id) in seq.template_sequence.iter().enumerate() {
		let template = templates
			.iter()
			.find(|t| t.id == template_id)
			.ok_or_else(|| anyhow::anyhow!("Template {} not found", template_id))?;

		output.push_str(&format!(
			"  Step {}: [{}] {}\n",
			i + 1,
			template
				.module
				.split("::")
				.last()
				.unwrap_or(&template.module),
			template.example
		));
	}

	output.push('\n');
	Ok(())
}

fn render_group(
	group: &LogGroup,
	templates: &[crate::Template],
	output: &mut String,
) -> Result<()> {
	let template = templates
		.iter()
		.find(|t| t.id == group.template_id)
		.ok_or_else(|| anyhow::anyhow!("Template {} not found", group.template_id))?;

	if group.count > 1 {
		// Multiple instances - show as collapsed
		let duration_ms = group
			.end_time
			.signed_duration_since(group.start_time)
			.num_milliseconds();

		output.push_str(&format!(
			"[{}×] {} {:?} {}: {} ({}ms)\n",
			group.count,
			group.start_time.format("%H:%M:%S%.3f"),
			template.level,
			template.module,
			template.example,
			duration_ms
		));
	} else {
		// Single instance - show as-is
		output.push_str(&format!(
			"{} {:?} {}: {}\n",
			group.start_time.format("%H:%M:%S%.3f"),
			template.level,
			template.module,
			template.example
		));
	}

	Ok(())
}
