"""
Discovery Engine - Suggest concepts and find cross-contract mappings.

Provides intelligent suggestions for concept classification and
discovers fields that represent the same concept across contracts.
"""

from __future__ import annotations

from typing import Any

from pycharter.wiki.shared.errors import GraphError


class DiscoveryEngine:
    """
    Discovers relationships and suggests concepts.

    Args:
        session: SQLAlchemy session
    """

    def __init__(self, session=None):
        self._session = session

    def _require_session(self):
        if self._session is None:
            raise GraphError("No database session configured")

    def suggest_concept(self, field_name: str) -> list[dict[str, Any]]:
        """
        Suggest concepts for a field based on its name.

        Uses existing field-concept mappings to suggest concepts
        for similarly-named fields.

        Args:
            field_name: Field name to get suggestions for

        Returns:
            List of suggested concept dicts with confidence scores
        """
        self._require_session()

        from sqlalchemy import text

        # Find concepts associated with similarly-named fields
        query = text("""
            SELECT c.id, c.name, c.description, COUNT(*) as match_count
            FROM pycharter.concepts c
            JOIN pycharter.field_concepts fc ON c.id = fc.concept_id
            JOIN pycharter.fields f ON f.id = fc.field_id
            WHERE f.name ILIKE :pattern
            GROUP BY c.id, c.name, c.description
            ORDER BY match_count DESC
            LIMIT 5
        """)

        result = self._session.execute(query, {"pattern": f"%{field_name}%"})
        return [
            {
                "id": str(row.id),
                "name": row.name,
                "description": row.description,
                "confidence": min(row.match_count / 10.0, 1.0),
            }
            for row in result
        ]

    def find_synonyms(self, concept_name: str) -> list[dict[str, Any]]:
        """
        Find fields that may be synonyms for a concept.

        Looks for fields mapped to concepts with 'same_as' relationships.

        Args:
            concept_name: Concept name to find synonyms for

        Returns:
            List of synonym field dicts
        """
        self._require_session()

        from sqlalchemy import text

        query = text("""
            SELECT DISTINCT f.id, f.contract_id, f.name
            FROM pycharter.fields f
            JOIN pycharter.field_relationships fr
              ON f.id = fr.source_field_id OR f.id = fr.target_field_id
            JOIN pycharter.field_concepts fc ON f.id = fc.field_id
            JOIN pycharter.concepts c ON c.id = fc.concept_id
            WHERE c.name = :concept_name
              AND fr.relationship_type = 'same_as'
            LIMIT 20
        """)

        result = self._session.execute(query, {"concept_name": concept_name})
        return [
            {
                "id": str(row.id),
                "contract_id": row.contract_id,
                "name": row.name,
            }
            for row in result
        ]

    def find_cross_contract_mappings(self, concept_name: str) -> list[dict[str, Any]]:
        """
        Find fields across contracts that share the same concept.

        Args:
            concept_name: Concept name to search for

        Returns:
            List of field dicts grouped by contract
        """
        self._require_session()

        from sqlalchemy import text

        query = text("""
            SELECT f.id, f.contract_id, f.name, f.data_type
            FROM pycharter.fields f
            JOIN pycharter.field_concepts fc ON f.id = fc.field_id
            JOIN pycharter.concepts c ON c.id = fc.concept_id
            WHERE c.name = :concept_name
            ORDER BY f.contract_id, f.name
        """)

        result = self._session.execute(query, {"concept_name": concept_name})
        return [
            {
                "id": str(row.id),
                "contract_id": row.contract_id,
                "name": row.name,
                "data_type": row.data_type,
            }
            for row in result
        ]
