import logging
from typing import Any

from semantic_models.schemas import SemanticModelSpec

logger = logging.getLogger(__name__)


def resolve_values(
    question: str,
    spec: SemanticModelSpec,
    semantic_model_id: str,
    version_id: str,
    llm_id: str | None = None,
    embedding_llm_id: str | None = None,
    private_editor_data: dict | None = None,
    trace_span: Any | None = None,
) -> dict[str, Any]:
    from semantic_models.resolution.resolver import ResolutionResult, resolve_terms

    logger.info("=" * 60)
    logger.info("TOOL: resolve_values")
    logger.info("=" * 60)
    logger.info("  question: %s", question[:100] + "..." if len(question) > 100 else question)
    logger.info("  llm_id: %s", llm_id)
    logger.info("  embedding_llm_id: %s", embedding_llm_id)

    spec_dict = spec.model_dump()

    try:
        logger.info("  Calling term resolver...")
        result: ResolutionResult = resolve_terms(
            question=question,
            spec=spec,
            spec_dict=spec_dict,
            semantic_model_id=semantic_model_id,
            version_id=version_id,
            llm_id=llm_id,
            embedding_llm_id=embedding_llm_id,
            private_editor_data=private_editor_data,
            trace_span=trace_span,
        )

        corrections = []
        for correction in result.corrections:
            corrections.append(
                {
                    "original": correction.original,
                    "resolved": correction.resolved,
                    "entity_id": correction.entity_id,
                    "attribute": correction.attribute,
                    "score": correction.score,
                    "match_type": correction.match_type,
                    "source": correction.source,
                    "llm_inferred": correction.llm_inferred,
                }
            )
            logger.info(
                "  Correction: '%s' -> '%s' (%s.%s, %s match, score=%.1f)",
                correction.original,
                correction.resolved,
                correction.entity_id,
                correction.attribute,
                correction.match_type,
                correction.score,
            )

        response = {
            "original_question": result.original_question,
            "resolved_question": result.resolved_question,
            "corrections": corrections,
        }

        logger.info(
            "TOOL RESULT: resolve_values found %d corrections",
            len(corrections),
        )
        return response

    except Exception as e:
        logger.warning("TOOL RESULT: resolve_values FAILED: %s", e)
        return {
            "original_question": question,
            "resolved_question": question,
            "corrections": [],
            "error": str(e),
        }


def get_glossary_terms(
    semantic_model_id: str,
    version_id: str,
    spec: SemanticModelSpec,
    question: str | None = None,
    limit: int = 50,
) -> list[dict]:
    from semantic_models.services.factory import get_semantic_models_service
    from semantic_models.services.glossary_utils import load_glossary_terms_for_prompt

    logger.info("=" * 60)
    logger.info("TOOL: get_glossary_terms")
    logger.info("=" * 60)
    logger.info("  semantic_model_id: %s", semantic_model_id)
    logger.info("  version_id: %s", version_id)
    logger.info("  question filter: %s", question[:50] if question else "None")
    logger.info("  limit: %d", limit)

    resolved_version_id = version_id
    if resolved_version_id is None:
        service = get_semantic_models_service()
        active_version = service.get_active_version(semantic_model_id)
        if active_version:
            resolved_version_id = active_version.id
            logger.info("  Resolved to active version: %s", resolved_version_id)
        else:
            logger.warning("  No active version found, returning empty list")
            return []

    try:
        all_terms = load_glossary_terms_for_prompt(
            semantic_model_id=semantic_model_id,
            spec=spec,
            version_id=resolved_version_id,
            limit=0,
        )

        logger.info("  Loaded %d glossary terms from version %s", len(all_terms), resolved_version_id)

        # Filter terms by relevance to question
        if question:
            question_lower = question.lower()
            terms = []
            for term in all_terms:
                term_name = term.get("term", "").lower()
                synonyms = [s.lower() for s in (term.get("synonyms") or [])]

                # Check if term or any synonym appears in the question
                if term_name in question_lower or any(syn in question_lower for syn in synonyms):
                    terms.append(term)

                if len(terms) >= limit:
                    break
        else:
            # No question filter, return up to limit
            terms = all_terms[:limit] if limit > 0 else all_terms

        for term in terms[:5]:  # Log first 5
            entity_name = term.get("entity_name", "vocabulary")
            target_name = term.get("target_name")
            if target_name:
                logger.info("  Term: '%s' -> %s.%s", term.get("term"), entity_name, target_name)
            else:
                logger.info("  Term: '%s' -> %s", term.get("term"), entity_name)
        if len(terms) > 5:
            logger.info("  ... and %d more terms", len(terms) - 5)

        logger.info(
            "TOOL RESULT: get_glossary_terms returned %d terms (filtered from %d)",
            len(terms),
            len(all_terms),
        )
        return terms

    except Exception as e:
        logger.warning("TOOL RESULT: get_glossary_terms FAILED: %s", e)
        return []
