use crate::inspect::smp::bundle::SmpAsciiPreview;
use crate::inspect::smp::map_title::{build_ascii_preview, is_ascii_preview_byte};

pub(in crate::inspect::smp) fn collect_ascii_previews_in_range(
    bytes: &[u8],
    start: usize,
    end: usize,
    min_len: usize,
) -> Vec<SmpAsciiPreview> {
    let mut previews = Vec::new();
    let mut run_start = None;
    let end = end.min(bytes.len());

    for index in start..end {
        let byte = bytes[index];
        if is_ascii_preview_byte(byte) {
            run_start.get_or_insert(index);
            continue;
        }

        if let Some(current_start) = run_start.take() {
            if index - current_start >= min_len {
                previews.push(build_ascii_preview(bytes, current_start, index));
            }
        }
    }

    if let Some(current_start) = run_start {
        if end - current_start >= min_len {
            previews.push(build_ascii_preview(bytes, current_start, end));
        }
    }

    previews
}

pub(in crate::inspect::smp) fn find_c_string_with_suffix_in_range(
    bytes: &[u8],
    start: usize,
    end: usize,
    suffix: &str,
) -> Option<usize> {
    let end = end.min(bytes.len());
    let suffix = suffix.as_bytes();
    let mut offset = start.min(end);

    while offset < end {
        if !is_ascii_preview_byte(bytes[offset]) {
            offset += 1;
            continue;
        }

        let run_start = offset;
        while offset < end && is_ascii_preview_byte(bytes[offset]) {
            offset += 1;
        }

        let run = &bytes[run_start..offset];
        if run.ends_with(suffix) {
            return Some(run_start);
        }
    }

    None
}

pub(in crate::inspect::smp) fn read_c_string_in_range(
    bytes: &[u8],
    start: usize,
    end: usize,
) -> Option<String> {
    if start >= end || start >= bytes.len() {
        return None;
    }

    let end = end.min(bytes.len());
    let mut cursor = start;
    while cursor < end && bytes[cursor] != 0 {
        cursor += 1;
    }
    if cursor == start {
        return None;
    }

    std::str::from_utf8(&bytes[start..cursor])
        .ok()
        .map(ToString::to_string)
}
