use crate::Result;
use std::io::{BufRead, BufReader};
use std::path::Path;

use super::parser::normalize_codex_session;
use super::schema::CodexRecord;

/// Parse Codex JSONL file and normalize to AgentEvent
pub fn normalize_codex_file(path: &Path) -> Result<Vec<agtrace_types::AgentEvent>> {
    let text = std::fs::read_to_string(path)?;

    let mut records: Vec<CodexRecord> = Vec::new();
    let mut session_id_from_meta: Option<String> = None;

    for line in text.lines() {
        let line = line.trim();
        if line.is_empty() {
            continue;
        }
        let record: CodexRecord = serde_json::from_str(line)?;

        // Extract session_id from session_meta record
        if let CodexRecord::SessionMeta(ref meta) = record {
            session_id_from_meta = Some(meta.payload.id.clone());
        }

        records.push(record);
    }

    // session_id should be extracted from file content, fallback to "unknown-session"
    let session_id = session_id_from_meta.unwrap_or_else(|| "unknown-session".to_string());

    Ok(normalize_codex_session(records, &session_id))
}

/// Extract cwd from a Codex session file by reading the first few records
pub fn extract_cwd_from_codex_file(path: &Path) -> Option<String> {
    let file = std::fs::File::open(path).ok()?;
    let reader = BufReader::new(file);

    for line in reader.lines().take(10).flatten() {
        if let Ok(record) = serde_json::from_str::<CodexRecord>(&line) {
            match record {
                CodexRecord::SessionMeta(meta) => {
                    return Some(meta.payload.cwd.clone());
                }
                CodexRecord::TurnContext(turn) => {
                    return Some(turn.payload.cwd.clone());
                }
                _ => continue,
            }
        }
    }
    None
}

#[derive(Debug)]
pub struct CodexHeader {
    pub session_id: Option<String>,
    pub cwd: Option<String>,
    pub timestamp: Option<String>,
    pub snippet: Option<String>,
}

/// Extract header information from Codex file (for scanning)
pub fn extract_codex_header(path: &Path) -> Result<CodexHeader> {
    let file = std::fs::File::open(path)?;
    let reader = BufReader::new(file);

    let mut session_id = None;
    let mut cwd = None;
    let mut timestamp = None;
    let mut snippet = None;

    for line in reader.lines().take(20).flatten() {
        if let Ok(record) = serde_json::from_str::<CodexRecord>(&line) {
            match &record {
                CodexRecord::SessionMeta(meta) => {
                    if session_id.is_none() {
                        session_id = Some(meta.payload.id.clone());
                    }
                    if cwd.is_none() {
                        cwd = Some(meta.payload.cwd.clone());
                    }
                    if timestamp.is_none() {
                        timestamp = Some(meta.timestamp.clone());
                    }
                }
                CodexRecord::TurnContext(turn) => {
                    if cwd.is_none() {
                        cwd = Some(turn.payload.cwd.clone());
                    }
                    if timestamp.is_none() {
                        timestamp = Some(turn.timestamp.clone());
                    }
                }
                CodexRecord::EventMsg(event) => {
                    if timestamp.is_none() {
                        timestamp = Some(event.timestamp.clone());
                    }
                    if snippet.is_none()
                        && let super::schema::EventMsgPayload::UserMessage(msg) = &event.payload
                    {
                        snippet = Some(msg.message.clone());
                    }
                }
                CodexRecord::ResponseItem(response) => {
                    if timestamp.is_none() {
                        timestamp = Some(response.timestamp.clone());
                    }
                    if snippet.is_none()
                        && let super::schema::ResponseItemPayload::Message(msg) = &response.payload
                        && msg.role == "user"
                    {
                        let text = msg.content.iter().find_map(|c| match c {
                            super::schema::MessageContent::InputText { text } => Some(text.clone()),
                            super::schema::MessageContent::OutputText { text } => {
                                Some(text.clone())
                            }
                            _ => None,
                        });
                        if let Some(t) = &text
                            && !t.contains("<environment_context>")
                        {
                            snippet = text;
                        }
                    }
                }
                _ => {}
            }

            if session_id.is_some() && cwd.is_some() && timestamp.is_some() && snippet.is_some() {
                break;
            }
        }
    }

    Ok(CodexHeader {
        session_id,
        cwd,
        timestamp,
        snippet,
    })
}

/// Check if a Codex session file is empty or incomplete
pub fn is_empty_codex_session(path: &Path) -> bool {
    let Ok(file) = std::fs::File::open(path) else {
        return true;
    };
    let reader = BufReader::new(file);

    let mut line_count = 0;
    let mut has_event = false;

    for line in reader.lines().take(20).flatten() {
        line_count += 1;
        if let Ok(record) = serde_json::from_str::<CodexRecord>(&line) {
            match record {
                CodexRecord::SessionMeta(_) | CodexRecord::TurnContext(_) => {
                    has_event = true;
                    break;
                }
                CodexRecord::EventMsg(_) | CodexRecord::ResponseItem(_) => {
                    has_event = true;
                    break;
                }
                _ => {}
            }
        }
    }

    line_count <= 2 && !has_event
}
