use super::AgentRunner;
use crate::core::agent::conversation::{
    build_messages_from_conversation, messages_from_conversation,
};
use crate::core::agent::harness_artifacts::{
    read_contract_summary, read_evaluation_summary, read_spec_summary,
};
use crate::core::agent::session::AgentSessionState;
use crate::core::agent::state::summarize_list;
use crate::llm::providers::gemini::wire::{Content, Part};
use tracing::{info, warn};

impl AgentRunner {
    pub(super) fn summarize_conversation_if_needed(
        &self,
        session_state: &mut AgentSessionState,
        preserve_recent_turns: usize,
        utilization: f64,
    ) {
        if utilization < 0.90 {
            return;
        }

        if session_state.conversation.len() <= preserve_recent_turns {
            return;
        }

        let preferred_split_at = session_state
            .conversation
            .len()
            .saturating_sub(preserve_recent_turns);

        // Context Manager: Find a safe split point that doesn't break tool call/output pairs.
        let split_at = session_state.find_safe_split_point(preferred_split_at);

        if split_at == 0 {
            return;
        }

        // Dynamic context discovery: Write full history to file before summarization
        // This allows the agent to recover details via grep_file if needed
        let history_file_path = self.persist_history_before_summarization(
            &session_state.conversation[..split_at],
            &session_state.session_id,
            session_state.stats.turns_executed,
            &session_state.modified_files,
            &session_state.executed_commands,
        );

        let base_summary = format!(
            "Summarized {} earlier turns to stay within context budget. Files: {}; Commands: {}; Warnings: {}.",
            split_at,
            summarize_list(&session_state.modified_files),
            summarize_list(&session_state.executed_commands),
            summarize_list(&session_state.warnings),
        );

        // Include history file reference in summary if available
        let summary = if let Some(path) = history_file_path {
            format!(
                "{}\n\nFull conversation history saved to: {}\nUse grep_file to search for specific details if needed.",
                base_summary,
                path.display()
            )
        } else {
            base_summary
        };
        let spec_summary = read_spec_summary(&self._workspace);
        let contract_summary = read_contract_summary(&self._workspace);
        let evaluation_summary = read_evaluation_summary(&self._workspace);
        let summary = {
            let mut enriched = summary;
            // Spec is appended after a blank line; the contract and evaluation
            // each on their own line, matching the prior render shape.
            if let Some(spec) = spec_summary {
                enriched.push_str("\n\n");
                enriched.push_str(&spec);
            }
            for extra in [contract_summary, evaluation_summary].into_iter().flatten() {
                enriched.push('\n');
                enriched.push_str(&extra);
            }
            enriched
        };

        let mut new_conversation = Vec::with_capacity(1 + preserve_recent_turns);
        new_conversation.push(Content::user_parts(vec![Part::Text {
            text: summary,
            thought_signature: None,
        }]));
        new_conversation.extend_from_slice(&session_state.conversation[split_at..]);
        session_state.conversation = new_conversation;
        session_state.messages = build_messages_from_conversation(&session_state.conversation);

        session_state.normalize();

        session_state.last_processed_message_idx = session_state.conversation.len();
    }

    /// Persist conversation history to a file before summarization
    ///
    /// This implements Cursor-style dynamic context discovery: full history
    /// is written to `.vtcode/history/` so the agent can recover details
    /// via grep_file if the summary loses important information.
    pub(super) fn persist_history_before_summarization(
        &self,
        conversation: &[Content],
        session_id: &str,
        turn_number: usize,
        modified_files: &[String],
        executed_commands: &[String],
    ) -> Option<std::path::PathBuf> {
        use crate::context::history_files::{HistoryFileManager, messages_to_history_messages};

        // Create history manager for this session
        let mut manager = HistoryFileManager::new(&self._workspace, session_id);

        // Convert the legacy Gemini conversation into provider-agnostic messages before writing it.
        let messages = messages_to_history_messages(&messages_from_conversation(conversation), 0);

        // Write history file
        match manager.write_history_sync(
            &messages,
            turn_number,
            "summarization",
            modified_files,
            executed_commands,
        ) {
            Ok(result) => {
                info!(
                    path = %result.file_path.display(),
                    messages = result.metadata.message_count,
                    "Persisted conversation history before summarization"
                );
                Some(result.file_path)
            }
            Err(e) => {
                warn!(error = %e, "Failed to persist conversation history before summarization");
                None
            }
        }
    }
}
