use std::path::Path;

pub fn is_generated_go(path: &Path, source: &str) -> bool {
    has_generated_comment(source) || has_generated_filename(path)
}

fn has_generated_comment(source: &str) -> bool {
    source
        .lines()
        .take(5)
        .any(|line| line.starts_with("// Code generated ") && line.contains("DO NOT EDIT."))
}

fn has_generated_filename(path: &Path) -> bool {
    path.file_name()
        .and_then(|name| name.to_str())
        .map(is_generated_name)
        .unwrap_or(false)
}

fn is_generated_name(name: &str) -> bool {
    name.ends_with(".pb.go") || name.starts_with("mock_") || name.starts_with("zz_generated")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generated_comment() {
        let source = "// Code generated by protoc. DO NOT EDIT.\npackage api";
        assert!(is_generated_go(Path::new("api.go"), source));
    }

    #[test]
    fn test_generated_filenames() {
        assert!(is_generated_go(Path::new("service.pb.go"), "package api"));
        assert!(is_generated_go(Path::new("mock_service.go"), "package api"));
        assert!(is_generated_go(
            Path::new("zz_generated.deepcopy.go"),
            "package api"
        ));
    }

    #[test]
    fn test_regular_go_file() {
        assert!(!is_generated_go(Path::new("service.go"), "package api"));
    }
}
