use crate::acp::{compose_do_split_prompt_text, DoOutgoingTraceParts};

pub(crate) const PROMPTS_LOG_FILE_NAME: &str = "prompts.log";

async fn open_prompts_log_append(
    run_dir: Option<&std::path::Path>,
) -> Result<Option<tokio::fs::File>, String> {
    let Some(dir) = run_dir else {
        return Ok(None);
    };
    let path = dir.join(PROMPTS_LOG_FILE_NAME);
    let f = tokio::fs::OpenOptions::new()
        .create(true)
        .append(true)
        .open(&path)
        .await
        .map_err(|e| format!("prompts.log open: {e}"))?;
    Ok(Some(f))
}

async fn prompts_log_write_formatted_line(
    f: &mut tokio::fs::File,
    line: &str,
) -> Result<(), String> {
    use tokio::io::AsyncWriteExt;
    f.write_all(line.as_bytes())
        .await
        .map_err(|e| format!("prompts.log write: {e}"))?;
    f.write_all(b"\n")
        .await
        .map_err(|e| format!("prompts.log nl: {e}"))?;
    Ok(())
}

async fn prompts_log_append_tagged_logical_lines(
    f: &mut tokio::fs::File,
    tag: &str,
    body: &str,
) -> Result<(), String> {
    for line in crate::output::logical_lines(body) {
        let l = crate::output::format_line(tag, line);
        prompts_log_write_formatted_line(f, &l).await?;
    }
    Ok(())
}

async fn prompts_log_flush(f: &mut tokio::fs::File) -> Result<(), String> {
    use tokio::io::AsyncWriteExt;
    f.flush()
        .await
        .map_err(|e| format!("prompts.log flush: {e}"))
}

pub(crate) async fn append_prompts_log_uniform(
    run_dir: Option<&std::path::Path>,
    _trace_stem: &str,
    bracket_label: &str,
    prompt_text: Option<&str>,
) -> Result<(), String> {
    let Some(mut f) = open_prompts_log_append(run_dir).await? else {
        return Ok(());
    };
    let tag = crate::output::WHO_U;
    if let Some(body) = prompt_text {
        prompts_log_append_tagged_logical_lines(&mut f, &tag, body).await?;
    } else {
        let summary = format!("[{bracket_label}...]");
        let l = crate::output::format_line(&tag, &summary);
        prompts_log_write_formatted_line(&mut f, &l).await?;
    }
    prompts_log_flush(&mut f).await
}

pub(crate) async fn append_prompts_log_do_plain(
    run_dir: Option<&std::path::Path>,
    parts: &DoOutgoingTraceParts<'_>,
    include_full_combined: bool,
) -> Result<(), String> {
    let Some(mut f) = open_prompts_log_append(run_dir).await? else {
        return Ok(());
    };
    let tag = crate::output::WHO_U;
    if include_full_combined {
        let combined = compose_do_split_prompt_text(parts);
        prompts_log_append_tagged_logical_lines(&mut f, &tag, &combined).await?;
    } else {
        let summary = "[do...]".to_string();
        let l = crate::output::format_line(&tag, &summary);
        prompts_log_write_formatted_line(&mut f, &l).await?;
    }
    prompts_log_flush(&mut f).await
}


#[cfg(test)]
mod kiss_cov_auto {
    #[test]
    fn kiss_cov_open_prompts_log_append() { let _ = stringify!(open_prompts_log_append); }

    #[test]
    fn kiss_cov_prompts_log_write_formatted_line() { let _ = stringify!(prompts_log_write_formatted_line); }

    #[test]
    fn kiss_cov_prompts_log_append_tagged_logical_lines() { let _ = stringify!(prompts_log_append_tagged_logical_lines); }

    #[test]
    fn kiss_cov_prompts_log_flush() { let _ = stringify!(prompts_log_flush); }

    #[test]
    fn kiss_cov_append_prompts_log_uniform() { let _ = stringify!(append_prompts_log_uniform); }

    #[test]
    fn kiss_cov_append_prompts_log_do_plain() { let _ = stringify!(append_prompts_log_do_plain); }

}

#[cfg(test)]
mod kiss_cov_gate_refs {
    use super::*;
    #[test]
    fn kiss_cov_unit_names() {
        let _ = open_prompts_log_append;
        let _ = prompts_log_append_tagged_logical_lines;
        let _ = prompts_log_flush;
        let _ = prompts_log_write_formatted_line;
    }
}
