//! Precise-graph-backed navigation when SCIP artifacts provide symbol coverage for a workspace.
//!
//! Selects precise-graph symbol coverage when SCIP artifacts are fresh; falls back to heuristic
//! corpora when precise partial coverage applies.

use super::*;

pub(in crate::mcp::server) struct DirectPreciseNavigationTarget {
    pub repository_id: String,
    pub root: PathBuf,
    pub precise_target: crate::graph::PreciseSymbolRecord,
    pub coverage_mode: PreciseCoverageMode,
    pub ingest_stats: PreciseIngestStats,
    pub graph: Arc<SymbolGraph>,
    pub source_files_discovered: usize,
}

impl FriggMcpServer {
    fn precise_symbol_matches_php_helper_kind(
        precise_symbol: &crate::graph::PreciseSymbolRecord,
        helper_kind: NavigationPhpHelperKind,
    ) -> bool {
        let symbol = precise_symbol.symbol.as_str();
        match helper_kind {
            NavigationPhpHelperKind::Translation => {
                symbol.starts_with("trans/") || symbol.contains(" trans/")
            }
            NavigationPhpHelperKind::Route => {
                symbol.starts_with("route/")
                    || symbol.contains(" route/")
                    || symbol.contains(" routes/")
            }
            NavigationPhpHelperKind::Config => {
                symbol.starts_with("config/") || symbol.contains(" config/")
            }
            NavigationPhpHelperKind::Env => symbol.starts_with("env/") || symbol.contains(" env/"),
        }
    }

    #[allow(clippy::too_many_arguments, clippy::type_complexity)]
    pub(in crate::mcp::server) fn try_precise_definition_fast_path(
        &self,
        corpora: &[Arc<RepositorySymbolCorpus>],
        repository_id_hint: Option<&str>,
        raw_path: &str,
        line: usize,
        column: Option<usize>,
        include_follow_up_structural: bool,
        limit: usize,
        freshness_basis: &Value,
    ) -> Result<Option<(Json<GoToDefinitionResponse>, String, String, String)>, ErrorData> {
        if repository_id_hint.is_none() && corpora.len() != 1 {
            return Ok(None);
        }

        let mut corpora = corpora.iter().collect::<Vec<_>>();
        corpora.sort_by(|left, right| {
            left.repository_id
                .cmp(&right.repository_id)
                .then(left.root.cmp(&right.root))
        });

        for corpus in corpora {
            if let Some(repository_id_hint) = repository_id_hint
                && corpus.repository_id != repository_id_hint
                && corpus.runtime_repository_id != repository_id_hint
            {
                continue;
            }
            let Ok(cached_precise_graph) = self
                .precise_graph_for_corpus(corpus.as_ref(), self.find_references_resource_budgets())
            else {
                continue;
            };
            let relative_path = Self::canonicalize_navigation_path(&corpus.root, raw_path);
            let graph = cached_precise_graph.graph;
            let Some(precise_target) = graph.select_precise_symbol_for_location(
                &corpus.repository_id,
                &relative_path,
                line,
                column,
            ) else {
                continue;
            };

            let mut precise_matches = graph
                .precise_occurrences_for_symbol(&corpus.repository_id, &precise_target.symbol)
                .into_iter()
                .filter(|occurrence| occurrence.is_definition())
                .map(|occurrence| NavigationLocation {
                    match_id: None,
                    stable_symbol_id: None,
                    symbol: if precise_target.display_name.is_empty() {
                        precise_target.symbol.clone()
                    } else {
                        precise_target.display_name.clone()
                    },
                    repository_id: corpus.repository_id.clone(),
                    path: Self::canonicalize_navigation_path(&corpus.root, &occurrence.path),
                    line: occurrence.range.start_line,
                    column: occurrence.range.start_column,
                    kind: Self::display_symbol_kind(&precise_target.kind),
                    container: None,
                    signature: None,
                    precision: Some(
                        Self::precise_match_precision(cached_precise_graph.coverage_mode)
                            .to_owned(),
                    ),
                    follow_up_structural: Vec::new(),
                })
                .collect::<Vec<_>>();
            Self::sort_navigation_locations(&mut precise_matches);
            if precise_matches.is_empty() {
                continue;
            }
            if precise_matches.len() > limit {
                precise_matches.truncate(limit);
            }
            if include_follow_up_structural {
                Self::populate_navigation_location_follow_up_structural(
                    &corpus.root,
                    &mut precise_matches,
                );
            }

            let precision =
                Self::precise_resolution_precision(cached_precise_graph.coverage_mode).to_owned();
            let metadata = json!({
                "precision": precision,
                "heuristic": false,
                "target_precise_symbol": precise_target.symbol.clone(),
                "resolution_source": "location_precise_cache",
                "precise": Self::precise_note_with_count(
                    cached_precise_graph.coverage_mode,
                    &cached_precise_graph.ingest_stats,
                    "definition_count",
                    precise_matches.len(),
                )
            });
            let metadata = Self::metadata_with_freshness_basis(metadata, freshness_basis);
            let (metadata, note) = Self::metadata_note_pair(metadata);
            return Ok(Some((
                Json(GoToDefinitionResponse {
                    matches: precise_matches,
                    result_handle: None,
                    mode: Self::navigation_mode_from_precision_label(Some(&precision)),
                    target_selection: None,
                    metadata,
                    note,
                }),
                corpus.repository_id.clone(),
                precise_target.symbol,
                precision,
            )));
        }

        Ok(None)
    }

    pub(in crate::mcp::server) fn canonicalize_navigation_path(
        root: &Path,
        raw_path: &str,
    ) -> String {
        let normalized_path = raw_path.replace('\\', "/");
        let path = PathBuf::from(normalized_path);
        let absolute_path = if path.is_absolute() {
            path
        } else {
            root.join(path)
        };
        Self::relative_display_path(root, &absolute_path)
    }

    pub(in crate::mcp::server) fn precise_definition_occurrence_for_symbol(
        graph: &SymbolGraph,
        repository_id: &str,
        symbol: &str,
    ) -> Option<crate::graph::PreciseOccurrenceRecord> {
        graph.precise_definition_occurrence_for_symbol(repository_id, symbol)
    }

    fn precise_navigation_candidate_anchor_rank(
        graph: &SymbolGraph,
        repository_id: &str,
        root: &Path,
        target_symbol: &SymbolDefinition,
        precise_target: &crate::graph::PreciseSymbolRecord,
    ) -> (u8, String, usize, usize) {
        let Some(definition) = Self::precise_definition_occurrence_for_symbol(
            graph,
            repository_id,
            &precise_target.symbol,
        ) else {
            return (4, String::new(), usize::MAX, usize::MAX);
        };

        let target_path = Self::relative_display_path(root, &target_symbol.path);
        let definition_path = Self::canonicalize_navigation_path(root, &definition.path);
        let rank = if definition_path == target_path
            && definition.range.start_line == target_symbol.line
            && definition.range.start_column == target_symbol.span.start_column
        {
            0
        } else if definition_path == target_path
            && definition.range.start_line == target_symbol.line
        {
            1
        } else if definition_path == target_path {
            2
        } else {
            3
        };

        (
            rank,
            definition_path,
            definition.range.start_line,
            definition.range.start_column,
        )
    }

    pub(in crate::mcp::server) fn matching_precise_symbols_for_resolved_target(
        graph: &SymbolGraph,
        repository_id: &str,
        root: &Path,
        symbol_query: &str,
        target_symbol: &SymbolDefinition,
    ) -> Vec<crate::graph::PreciseSymbolRecord> {
        let mut candidates = graph.matching_precise_symbols_for_navigation(
            repository_id,
            symbol_query,
            &target_symbol.name,
        );
        candidates.sort_by(|left, right| {
            Self::precise_navigation_candidate_anchor_rank(
                graph,
                repository_id,
                root,
                target_symbol,
                left,
            )
            .cmp(&Self::precise_navigation_candidate_anchor_rank(
                graph,
                repository_id,
                root,
                target_symbol,
                right,
            ))
            .then(left.symbol.cmp(&right.symbol))
            .then(left.display_name.cmp(&right.display_name))
            .then(left.kind.cmp(&right.kind))
        });
        candidates
    }

    pub(in crate::mcp::server) fn select_precise_symbol_for_resolved_target(
        graph: &SymbolGraph,
        repository_id: &str,
        root: &Path,
        symbol_query: &str,
        target_symbol: &SymbolDefinition,
    ) -> Option<crate::graph::PreciseSymbolRecord> {
        Self::matching_precise_symbols_for_resolved_target(
            graph,
            repository_id,
            root,
            symbol_query,
            target_symbol,
        )
        .into_iter()
        .next()
    }

    pub(in crate::mcp::server) fn select_direct_precise_navigation_target(
        &self,
        corpora: &[Arc<RepositorySymbolCorpus>],
        symbol_query: &str,
        resource_budgets: FindReferencesResourceBudgets,
    ) -> Result<Option<DirectPreciseNavigationTarget>, ErrorData> {
        let mut best_rank: Option<(usize, usize, String, usize, usize, String, String)> = None;
        let mut best_target: Option<DirectPreciseNavigationTarget> = None;
        for corpus in corpora {
            let cached_precise_graph =
                self.precise_graph_for_corpus(corpus.as_ref(), resource_budgets)?;
            let graph = cached_precise_graph.graph;
            for (symbol_rank, precise_target) in graph
                .matching_precise_symbols_for_navigation(
                    &corpus.repository_id,
                    symbol_query,
                    symbol_query,
                )
                .into_iter()
                .enumerate()
            {
                let definition = graph.precise_definition_occurrence_for_symbol(
                    &corpus.repository_id,
                    &precise_target.symbol,
                );
                let candidate_rank = (
                    symbol_rank,
                    usize::from(definition.is_none()),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.path.clone())
                        .unwrap_or_default(),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.range.start_line)
                        .unwrap_or(usize::MAX),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.range.start_column)
                        .unwrap_or(usize::MAX),
                    corpus.repository_id.clone(),
                    precise_target.symbol.clone(),
                );
                let candidate_target = DirectPreciseNavigationTarget {
                    repository_id: corpus.repository_id.clone(),
                    root: corpus.root.clone(),
                    precise_target,
                    coverage_mode: cached_precise_graph.coverage_mode,
                    ingest_stats: cached_precise_graph.ingest_stats.clone(),
                    graph: Arc::clone(&graph),
                    source_files_discovered: corpus.source_paths.len(),
                };
                if best_rank
                    .as_ref()
                    .is_none_or(|current_best| candidate_rank < *current_best)
                {
                    best_rank = Some(candidate_rank);
                    best_target = Some(candidate_target);
                }
            }
        }

        Ok(best_target)
    }

    pub(in crate::mcp::server) fn select_direct_precise_navigation_target_for_php_helper(
        &self,
        corpora: &[Arc<RepositorySymbolCorpus>],
        symbol_query: &str,
        helper_kind: NavigationPhpHelperKind,
        resource_budgets: FindReferencesResourceBudgets,
    ) -> Result<Option<DirectPreciseNavigationTarget>, ErrorData> {
        let mut best_rank: Option<(usize, usize, String, usize, usize, String, String)> = None;
        let mut best_target: Option<DirectPreciseNavigationTarget> = None;
        for corpus in corpora {
            let cached_precise_graph =
                self.precise_graph_for_corpus(corpus.as_ref(), resource_budgets)?;
            let graph = cached_precise_graph.graph;
            for (symbol_rank, precise_target) in graph
                .matching_precise_symbols_for_navigation(
                    &corpus.repository_id,
                    symbol_query,
                    symbol_query,
                )
                .into_iter()
                .filter(|precise_symbol| {
                    Self::precise_symbol_matches_php_helper_kind(precise_symbol, helper_kind)
                })
                .enumerate()
            {
                let definition = graph.precise_definition_occurrence_for_symbol(
                    &corpus.repository_id,
                    &precise_target.symbol,
                );
                let candidate_rank = (
                    symbol_rank,
                    usize::from(definition.is_none()),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.path.clone())
                        .unwrap_or_default(),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.range.start_line)
                        .unwrap_or(usize::MAX),
                    definition
                        .as_ref()
                        .map(|occurrence| occurrence.range.start_column)
                        .unwrap_or(usize::MAX),
                    corpus.repository_id.clone(),
                    precise_target.symbol.clone(),
                );
                let candidate_target = DirectPreciseNavigationTarget {
                    repository_id: corpus.repository_id.clone(),
                    root: corpus.root.clone(),
                    precise_target,
                    coverage_mode: cached_precise_graph.coverage_mode,
                    ingest_stats: cached_precise_graph.ingest_stats.clone(),
                    graph: Arc::clone(&graph),
                    source_files_discovered: corpus.source_paths.len(),
                };
                if best_rank
                    .as_ref()
                    .is_none_or(|current_best| candidate_rank < *current_best)
                {
                    best_rank = Some(candidate_rank);
                    best_target = Some(candidate_target);
                }
            }
        }

        Ok(best_target)
    }

    pub(in crate::mcp::server) fn direct_precise_definition_matches_for_target(
        target: &DirectPreciseNavigationTarget,
        symbol_fallback: &str,
    ) -> Vec<NavigationLocation> {
        let mut matches = target
            .graph
            .precise_occurrences_for_symbol(&target.repository_id, &target.precise_target.symbol)
            .into_iter()
            .filter(|occurrence| occurrence.is_definition())
            .map(|occurrence| NavigationLocation {
                match_id: None,
                stable_symbol_id: None,
                symbol: if target.precise_target.display_name.is_empty() {
                    symbol_fallback.to_owned()
                } else {
                    target.precise_target.display_name.clone()
                },
                repository_id: target.repository_id.clone(),
                path: Self::canonicalize_navigation_path(&target.root, &occurrence.path),
                line: occurrence.range.start_line,
                column: occurrence.range.start_column,
                kind: Self::display_symbol_kind(&target.precise_target.kind),
                container: None,
                signature: None,
                precision: Some(Self::precise_match_precision(target.coverage_mode).to_owned()),
                follow_up_structural: Vec::new(),
            })
            .collect::<Vec<_>>();
        Self::sort_navigation_locations(&mut matches);
        matches
    }

    fn precise_relationships_to_symbol_by_kind(
        graph: &SymbolGraph,
        repository_id: &str,
        to_symbol: &str,
        kinds: &[PreciseRelationshipKind],
    ) -> Vec<crate::graph::PreciseRelationshipRecord> {
        graph.precise_relationships_to_symbol_by_kinds(repository_id, to_symbol, kinds)
    }

    pub(in crate::mcp::server) fn sort_navigation_locations(matches: &mut [NavigationLocation]) {
        matches.sort_by(|left, right| {
            left.repository_id
                .cmp(&right.repository_id)
                .then(left.path.cmp(&right.path))
                .then(left.line.cmp(&right.line))
                .then(left.column.cmp(&right.column))
                .then(left.symbol.cmp(&right.symbol))
                .then(left.kind.cmp(&right.kind))
                .then(left.precision.cmp(&right.precision))
        });
    }

    pub(in crate::mcp::server) fn sort_implementation_matches(matches: &mut [ImplementationMatch]) {
        matches.sort_by(|left, right| {
            left.repository_id
                .cmp(&right.repository_id)
                .then(left.path.cmp(&right.path))
                .then(left.line.cmp(&right.line))
                .then(left.column.cmp(&right.column))
                .then(left.symbol.cmp(&right.symbol))
                .then(left.kind.cmp(&right.kind))
                .then(left.relation.cmp(&right.relation))
                .then(left.precision.cmp(&right.precision))
                .then(left.fallback_reason.cmp(&right.fallback_reason))
        });
    }

    pub(in crate::mcp::server) fn precise_implementation_matches_for_symbol(
        graph: &SymbolGraph,
        repository_id: &str,
        root: &Path,
        coverage_mode: PreciseCoverageMode,
        precise_target: &crate::graph::PreciseSymbolRecord,
    ) -> Vec<ImplementationMatch> {
        let precision = Self::precise_match_precision(coverage_mode).to_owned();
        let mut matches = Self::precise_relationships_to_symbol_by_kind(
            graph,
            repository_id,
            &precise_target.symbol,
            &[
                PreciseRelationshipKind::Implementation,
                PreciseRelationshipKind::TypeDefinition,
            ],
        )
        .into_iter()
        .filter_map(|relationship| {
            let implementation_symbol = graph
                .precise_symbol(repository_id, &relationship.from_symbol)?
                .clone();
            let definition = Self::precise_definition_occurrence_for_symbol(
                graph,
                repository_id,
                &relationship.from_symbol,
            )?;
            Some(ImplementationMatch {
                match_id: None,
                stable_symbol_id: None,
                symbol: if implementation_symbol.display_name.is_empty() {
                    implementation_symbol.symbol
                } else {
                    implementation_symbol.display_name
                },
                kind: Self::display_symbol_kind(&implementation_symbol.kind),
                repository_id: repository_id.to_owned(),
                path: Self::canonicalize_navigation_path(root, &definition.path),
                line: definition.range.start_line,
                column: definition.range.start_column,
                relation: Some(relationship.kind.as_str().to_owned()),
                container: None,
                signature: None,
                precision: Some(precision.clone()),
                fallback_reason: None,
                follow_up_structural: Vec::new(),
            })
        })
        .collect::<Vec<_>>();
        Self::sort_implementation_matches(&mut matches);
        matches
    }

    pub(in crate::mcp::server) fn precise_implementation_matches_from_occurrences(
        graph: &SymbolGraph,
        target_corpus: &RepositorySymbolCorpus,
        root: &Path,
        target_symbol_name: &str,
        coverage_mode: PreciseCoverageMode,
        precise_target: &crate::graph::PreciseSymbolRecord,
    ) -> Vec<ImplementationMatch> {
        let precision = Self::precise_match_precision(coverage_mode).to_owned();
        let target_name = if precise_target.display_name.is_empty() {
            target_symbol_name
        } else {
            precise_target.display_name.as_str()
        };

        let mut matches = graph
            .precise_references_for_symbol(&target_corpus.repository_id, &precise_target.symbol)
            .into_iter()
            .filter_map(|occurrence| {
                let enclosing_symbol = Self::precise_enclosing_symbol_for_occurrence(
                    target_corpus,
                    root,
                    &occurrence,
                    None,
                )?;
                if enclosing_symbol.kind.as_str() != "impl" {
                    return None;
                }

                let (implemented_trait, implementing_type) =
                    parse_rust_impl_signature(enclosing_symbol.name.as_str())?;
                let (symbol, kind, path, line, column, relation) =
                    if let Some(implemented_trait) = implemented_trait {
                        if implemented_trait.eq_ignore_ascii_case(target_name) {
                            let implementing_symbol = graph.select_precise_symbol_for_navigation(
                                &target_corpus.repository_id,
                                implementing_type,
                                implementing_type,
                            )?;
                            let definition = Self::precise_definition_occurrence_for_symbol(
                                graph,
                                &target_corpus.repository_id,
                                &implementing_symbol.symbol,
                            )?;
                            (
                                if implementing_symbol.display_name.is_empty() {
                                    implementing_symbol.symbol
                                } else {
                                    implementing_symbol.display_name
                                },
                                Self::display_symbol_kind(&implementing_symbol.kind),
                                Self::canonicalize_navigation_path(root, &definition.path),
                                definition.range.start_line,
                                definition.range.start_column,
                                Some("implementation".to_owned()),
                            )
                        } else if implementing_type.eq_ignore_ascii_case(target_name) {
                            (
                                enclosing_symbol.name.clone(),
                                Self::display_symbol_kind(enclosing_symbol.kind.as_str()),
                                Self::relative_display_path(root, &enclosing_symbol.path),
                                enclosing_symbol.line,
                                enclosing_symbol.span.start_column,
                                Some("type_definition".to_owned()),
                            )
                        } else {
                            return None;
                        }
                    } else if implementing_type.eq_ignore_ascii_case(target_name) {
                        (
                            enclosing_symbol.name.clone(),
                            Self::display_symbol_kind(enclosing_symbol.kind.as_str()),
                            Self::relative_display_path(root, &enclosing_symbol.path),
                            enclosing_symbol.line,
                            enclosing_symbol.span.start_column,
                            Some("type_definition".to_owned()),
                        )
                    } else {
                        return None;
                    };

                let (container, signature) =
                    Self::symbol_context_for_stable_id(target_corpus, &enclosing_symbol.stable_id);
                Some(ImplementationMatch {
                    match_id: None,
                    stable_symbol_id: Some(enclosing_symbol.stable_id.clone()),
                    symbol,
                    kind,
                    repository_id: target_corpus.repository_id.clone(),
                    path,
                    line,
                    column,
                    relation,
                    container,
                    signature,
                    precision: Some(precision.clone()),
                    fallback_reason: None,
                    follow_up_structural: Vec::new(),
                })
            })
            .collect::<Vec<_>>();
        Self::sort_implementation_matches(&mut matches);
        matches.dedup_by(|left, right| {
            left.repository_id == right.repository_id
                && left.path == right.path
                && left.line == right.line
                && left.column == right.column
                && left.symbol == right.symbol
                && left.kind == right.kind
                && left.relation == right.relation
                && left.precision == right.precision
                && left.fallback_reason == right.fallback_reason
        });
        matches
    }

    pub(in crate::mcp::server) fn precise_incoming_matches_from_relationships(
        graph: &SymbolGraph,
        repository_id: &str,
        root: &Path,
        target_symbol_name: &str,
        coverage_mode: PreciseCoverageMode,
        precise_target: &crate::graph::PreciseSymbolRecord,
    ) -> Vec<CallHierarchyMatch> {
        let precision = Self::precise_match_precision(coverage_mode).to_owned();
        let mut source_cache: BTreeMap<String, Option<String>> = BTreeMap::new();
        let mut matches = Self::precise_relationships_to_symbol_by_kind(
            graph,
            repository_id,
            &precise_target.symbol,
            &[PreciseRelationshipKind::Reference],
        )
        .into_iter()
        .filter_map(|relationship| {
            let caller_symbol = graph
                .precise_symbol(repository_id, &relationship.from_symbol)?
                .clone();
            let caller_definition = Self::precise_definition_occurrence_for_symbol(
                graph,
                repository_id,
                &relationship.from_symbol,
            )?;
            let relation = if graph
                .precise_references_for_symbol(repository_id, &precise_target.symbol)
                .into_iter()
                .filter(|occurrence| occurrence.path == caller_definition.path)
                .any(|occurrence| {
                    Self::precise_occurrence_has_call_like_source(
                        root,
                        precise_target,
                        &occurrence,
                        &mut source_cache,
                    )
                }) {
                "calls"
            } else {
                "refers_to"
            };
            Some(CallHierarchyMatch {
                match_id: None,
                source_stable_symbol_id: None,
                target_stable_symbol_id: None,
                source_symbol: if caller_symbol.display_name.is_empty() {
                    caller_symbol.symbol
                } else {
                    caller_symbol.display_name
                },
                target_symbol: if precise_target.display_name.is_empty() {
                    target_symbol_name.to_owned()
                } else {
                    precise_target.display_name.clone()
                },
                repository_id: repository_id.to_owned(),
                path: Self::canonicalize_navigation_path(root, &caller_definition.path),
                line: caller_definition.range.start_line,
                column: caller_definition.range.start_column,
                relation: relation.to_owned(),
                source_container: None,
                target_container: None,
                source_signature: None,
                target_signature: None,
                precision: Some(precision.clone()),
                call_path: None,
                call_line: None,
                call_column: None,
                call_end_line: None,
                call_end_column: None,
                follow_up_structural: Vec::new(),
            })
        })
        .collect::<Vec<_>>();
        Self::sort_call_hierarchy_matches(&mut matches);
        matches
    }

    fn precise_enclosing_symbol_for_occurrence<'a>(
        target_corpus: &'a RepositorySymbolCorpus,
        root: &Path,
        occurrence: &crate::graph::PreciseOccurrenceRecord,
        exclude_symbol_id: Option<&str>,
    ) -> Option<&'a SymbolDefinition> {
        let occurrence_path = Self::canonicalize_navigation_path(root, &occurrence.path);
        target_corpus
            .symbols_by_relative_path
            .get(&occurrence_path)
            .into_iter()
            .flat_map(|indices| indices.iter())
            .map(|index| &target_corpus.symbols[*index])
            .filter(|symbol| {
                exclude_symbol_id
                    .map(|exclude| symbol.stable_id != exclude)
                    .unwrap_or(true)
            })
            .filter(|symbol| {
                Self::source_span_contains_precise_range(&symbol.span, &occurrence.range)
            })
            .min_by(|left, right| {
                let left_span = left.span.end_line.saturating_sub(left.span.start_line);
                let right_span = right.span.end_line.saturating_sub(right.span.start_line);
                let left_column_span = if left_span == 0 {
                    left.span.end_column.saturating_sub(left.span.start_column)
                } else {
                    usize::MAX
                };
                let right_column_span = if right_span == 0 {
                    right
                        .span
                        .end_column
                        .saturating_sub(right.span.start_column)
                } else {
                    usize::MAX
                };
                left_span
                    .cmp(&right_span)
                    .then(left_column_span.cmp(&right_column_span))
                    .then(left.span.start_line.cmp(&right.span.start_line))
                    .then(left.span.start_column.cmp(&right.span.start_column))
                    .then(left.stable_id.cmp(&right.stable_id))
            })
    }

    pub(in crate::mcp::server) fn precise_incoming_matches_from_occurrences(
        graph: &SymbolGraph,
        target_corpus: &RepositorySymbolCorpus,
        root: &Path,
        target_symbol_name: &str,
        coverage_mode: PreciseCoverageMode,
        precise_target: &crate::graph::PreciseSymbolRecord,
        exclude_symbol_id: &str,
    ) -> Vec<CallHierarchyMatch> {
        let precision = Self::precise_match_precision(coverage_mode).to_owned();
        let mut source_cache: BTreeMap<String, Option<String>> = BTreeMap::new();
        let mut matches = graph
            .precise_references_for_symbol(&target_corpus.repository_id, &precise_target.symbol)
            .into_iter()
            .filter_map(|occurrence| {
                let enclosing_symbol = Self::precise_enclosing_symbol_for_occurrence(
                    target_corpus,
                    root,
                    &occurrence,
                    Some(exclude_symbol_id),
                )?;
                let relation = Self::classify_precise_incoming_occurrence_relation(
                    root,
                    precise_target,
                    &occurrence,
                    &mut source_cache,
                );
                let (source_container, source_signature) =
                    Self::symbol_context_for_stable_id(target_corpus, &enclosing_symbol.stable_id);
                let (call_path, call_line, call_column, call_end_line, call_end_column) =
                    Self::precise_call_site_fields(root, &occurrence);
                Some(CallHierarchyMatch {
                    match_id: None,
                    source_stable_symbol_id: Some(enclosing_symbol.stable_id.clone()),
                    target_stable_symbol_id: None,
                    source_symbol: enclosing_symbol.name.clone(),
                    target_symbol: if precise_target.display_name.is_empty() {
                        target_symbol_name.to_owned()
                    } else {
                        precise_target.display_name.clone()
                    },
                    repository_id: target_corpus.repository_id.clone(),
                    path: Self::relative_display_path(root, &enclosing_symbol.path),
                    line: enclosing_symbol.line,
                    column: enclosing_symbol.span.start_column,
                    relation: relation.to_owned(),
                    source_container,
                    target_container: None,
                    source_signature,
                    target_signature: None,
                    precision: Some(precision.clone()),
                    call_path,
                    call_line,
                    call_column,
                    call_end_line,
                    call_end_column,
                    follow_up_structural: Vec::new(),
                })
            })
            .collect::<Vec<_>>();
        Self::sort_call_hierarchy_matches(&mut matches);
        matches.dedup_by(|left, right| {
            left.repository_id == right.repository_id
                && left.path == right.path
                && left.line == right.line
                && left.column == right.column
                && left.source_symbol == right.source_symbol
                && left.target_symbol == right.target_symbol
                && left.relation == right.relation
                && left.precision == right.precision
                && left.call_path == right.call_path
                && left.call_line == right.call_line
                && left.call_column == right.call_column
                && left.call_end_line == right.call_end_line
                && left.call_end_column == right.call_end_column
        });
        matches
    }

    fn classify_precise_incoming_occurrence_relation(
        root: &Path,
        precise_target: &crate::graph::PreciseSymbolRecord,
        occurrence: &crate::graph::PreciseOccurrenceRecord,
        source_cache: &mut BTreeMap<String, Option<String>>,
    ) -> &'static str {
        if Self::precise_occurrence_has_call_like_source(
            root,
            precise_target,
            occurrence,
            source_cache,
        ) {
            "calls"
        } else {
            "refers_to"
        }
    }

    fn precise_occurrence_has_call_like_source(
        root: &Path,
        precise_target: &crate::graph::PreciseSymbolRecord,
        occurrence: &crate::graph::PreciseOccurrenceRecord,
        source_cache: &mut BTreeMap<String, Option<String>>,
    ) -> bool {
        let source = source_cache
            .entry(occurrence.path.clone())
            .or_insert_with(|| {
                let occurrence_path = Path::new(&occurrence.path);
                let absolute_path = if occurrence_path.is_absolute() {
                    occurrence_path.to_path_buf()
                } else {
                    root.join(occurrence_path)
                };
                fs::read_to_string(absolute_path).ok()
            })
            .as_deref();
        let Some(source) = source else {
            return false;
        };
        let Some(line) = Self::source_line_for_precise_range(source, &occurrence.range) else {
            return false;
        };
        let target_name = Self::precise_target_call_name(precise_target);
        line.match_indices(target_name.as_str()).any(|(index, _)| {
            let suffix_start = index.saturating_add(target_name.len()).min(line.len());
            line.get(suffix_start..)
                .map(rust_source_suffix_looks_like_call)
                .unwrap_or(false)
        })
    }

    pub(in crate::mcp::server) fn precise_symbol_label(
        precise_symbol: &crate::graph::PreciseSymbolRecord,
    ) -> String {
        crate::graph::precise_navigation_identifier(&precise_symbol.display_name)
            .or_else(|| crate::graph::precise_navigation_identifier(&precise_symbol.symbol))
            .unwrap_or_else(|| precise_symbol.symbol.clone())
    }

    fn precise_target_call_name(precise_target: &crate::graph::PreciseSymbolRecord) -> String {
        Self::precise_symbol_label(precise_target)
    }

    fn source_line_for_precise_range<'a>(
        source: &'a str,
        range: &crate::graph::PreciseRange,
    ) -> Option<&'a str> {
        source.lines().nth(range.start_line.saturating_sub(1))
    }

    #[allow(clippy::too_many_arguments)]
    pub(in crate::mcp::server) fn precise_outgoing_matches_from_occurrences(
        graph: &SymbolGraph,
        target_corpus: &RepositorySymbolCorpus,
        root: &Path,
        source_symbol_name: &str,
        coverage_mode: PreciseCoverageMode,
        precise_target: &crate::graph::PreciseSymbolRecord,
        enclosing_symbol_id: &str,
        occurrence_cache: &mut BTreeMap<String, Vec<crate::graph::PreciseOccurrenceRecord>>,
        source_cache: &mut BTreeMap<String, Option<String>>,
    ) -> Vec<CallHierarchyMatch> {
        let precision = Self::precise_match_precision(coverage_mode).to_owned();
        let source_definition = match Self::precise_definition_occurrence_for_symbol(
            graph,
            &target_corpus.repository_id,
            &precise_target.symbol,
        ) {
            Some(definition) => definition,
            None => return Vec::new(),
        };
        let source_path = Self::canonicalize_navigation_path(root, &source_definition.path);
        let file_occurrences = occurrence_cache
            .entry(source_path.clone())
            .or_insert_with(|| {
                graph.precise_occurrences_for_file(&target_corpus.repository_id, &source_path)
            });
        let mut matches = file_occurrences
            .iter()
            .filter(|occurrence| !occurrence.is_definition())
            .filter(|occurrence| occurrence.symbol != precise_target.symbol)
            .filter_map(|occurrence| {
                let enclosing_symbol = Self::precise_enclosing_symbol_for_occurrence(
                    target_corpus,
                    root,
                    occurrence,
                    None,
                )?;
                if enclosing_symbol.stable_id != enclosing_symbol_id {
                    return None;
                }

                let callee_symbol = graph
                    .precise_symbol(&target_corpus.repository_id, &occurrence.symbol)?
                    .clone();
                if !Self::precise_occurrence_has_call_like_source(
                    root,
                    &callee_symbol,
                    occurrence,
                    source_cache,
                ) {
                    return None;
                }
                let callee_definition = Self::precise_definition_occurrence_for_symbol(
                    graph,
                    &target_corpus.repository_id,
                    &occurrence.symbol,
                )?;
                let (source_container, source_signature) =
                    Self::symbol_context_for_stable_id(target_corpus, &enclosing_symbol.stable_id);
                let (call_path, call_line, call_column, call_end_line, call_end_column) =
                    Self::precise_call_site_fields(root, occurrence);
                Some(CallHierarchyMatch {
                    match_id: None,
                    source_stable_symbol_id: Some(enclosing_symbol.stable_id.clone()),
                    target_stable_symbol_id: None,
                    source_symbol: if precise_target.display_name.is_empty() {
                        source_symbol_name.to_owned()
                    } else {
                        precise_target.display_name.clone()
                    },
                    target_symbol: Self::precise_symbol_label(&callee_symbol),
                    repository_id: target_corpus.repository_id.clone(),
                    path: Self::canonicalize_navigation_path(root, &callee_definition.path),
                    line: callee_definition.range.start_line,
                    column: callee_definition.range.start_column,
                    relation: "calls".to_owned(),
                    source_container,
                    target_container: None,
                    source_signature,
                    target_signature: None,
                    precision: Some(precision.clone()),
                    call_path,
                    call_line,
                    call_column,
                    call_end_line,
                    call_end_column,
                    follow_up_structural: Vec::new(),
                })
            })
            .collect::<Vec<_>>();
        Self::sort_call_hierarchy_matches(&mut matches);
        matches.dedup_by(|left, right| {
            left.repository_id == right.repository_id
                && left.path == right.path
                && left.line == right.line
                && left.column == right.column
                && left.source_symbol == right.source_symbol
                && left.target_symbol == right.target_symbol
                && left.relation == right.relation
                && left.precision == right.precision
                && left.call_path == right.call_path
                && left.call_line == right.call_line
                && left.call_column == right.call_column
                && left.call_end_line == right.call_end_line
                && left.call_end_column == right.call_end_column
        });
        matches
    }

    fn position_leq(
        left_line: usize,
        left_column: usize,
        right_line: usize,
        right_column: usize,
    ) -> bool {
        (left_line, left_column) <= (right_line, right_column)
    }

    fn source_span_contains_precise_range(
        span: &SourceSpan,
        range: &crate::graph::PreciseRange,
    ) -> bool {
        Self::position_leq(
            span.start_line,
            span.start_column,
            range.start_line,
            range.start_column,
        ) && Self::position_leq(
            range.end_line,
            range.end_column,
            span.end_line,
            span.end_column,
        )
    }

    pub(in crate::mcp::server) fn precise_kind_numeric_value(kind: &str) -> Option<i32> {
        kind.strip_prefix("kind_")
            .unwrap_or(kind)
            .parse::<i32>()
            .ok()
    }

    pub(in crate::mcp::server) fn display_symbol_kind(kind: &str) -> Option<String> {
        let normalized = kind.trim();
        if normalized.is_empty() {
            return None;
        }

        if let Some(value) = Self::precise_kind_numeric_value(normalized)
            && let Some(kind) = ScipSymbolKind::from_i32(value)
        {
            return Some(Self::camel_to_snake_case(&format!("{kind:?}")));
        }

        Some(Self::camel_to_snake_case(normalized))
    }

    fn camel_to_snake_case(raw: &str) -> String {
        let mut output = String::with_capacity(raw.len());
        let mut previous_was_separator = false;
        let mut previous_was_lower_or_digit = false;

        for character in raw.chars() {
            if matches!(character, '_' | '-' | ' ' | '\t') {
                if !output.ends_with('_') && !output.is_empty() {
                    output.push('_');
                }
                previous_was_separator = true;
                previous_was_lower_or_digit = false;
                continue;
            }

            if character.is_ascii_uppercase()
                && !output.is_empty()
                && !previous_was_separator
                && previous_was_lower_or_digit
            {
                output.push('_');
            }

            output.push(character.to_ascii_lowercase());
            previous_was_separator = false;
            previous_was_lower_or_digit =
                character.is_ascii_lowercase() || character.is_ascii_digit();
        }

        output
    }
}
