"""
SHIP Protocol CrewAI Tools

Provides CrewAI-compatible tools for AI code reliability scoring and detection.

Design Principles:
    - Antifragile: Never crash the agent -- always return useful info on errors
    - Observable: Rich structured output for agent reasoning
    - Composable: Each tool is independent and works with any CrewAI agent
"""

import json
from typing import Any, Type

from crewai.tools import BaseTool
from pydantic import BaseModel, Field

from .client import SHIPClient, DEFAULT_BASE_URL, DEFAULT_TIMEOUT


class ScoreInput(BaseModel):
    """Input schema for SHIP score tool."""

    repo: str = Field(
        description=(
            "GitHub repository to score, in 'owner/repo' format "
            "(e.g. 'facebook/react', 'microsoft/vscode')"
        )
    )


class DetectInput(BaseModel):
    """Input schema for SHIP detect tool."""

    code: str = Field(
        description="Source code to analyze for AI-generation patterns"
    )
    language: str = Field(
        default="python",
        description="Programming language of the code (python, typescript, javascript, go, rust, etc.)",
    )


class SHIPScoreTool(BaseTool):
    """
    Score a GitHub repository for AI code reliability.

    Returns a SHIP Score (0-100) predicting success probability of AI-generated
    code in the repository. Use this to evaluate code quality before relying
    on or modifying AI-generated code.

    Example:
        tool = SHIPScoreTool()
        result = tool._run(repo="owner/repo")
    """

    name: str = "SHIP Score"
    description: str = (
        "Score a GitHub repository for AI code reliability. "
        "Returns a SHIP Score (0-100) predicting the success probability of AI-generated code. "
        "Input: repository in 'owner/repo' format. "
        "Output: score, grade (A+ to F), and reliability breakdown."
    )
    args_schema: Type[BaseModel] = ScoreInput

    # Client configuration -- set these to customize API connection
    base_url: str = DEFAULT_BASE_URL
    api_key: str = ""
    timeout: float = DEFAULT_TIMEOUT

    def _run(self, repo: str, **kwargs: Any) -> str:
        """
        Score a GitHub repository.

        Args:
            repo: GitHub repository in "owner/repo" format

        Returns:
            JSON string with score, grade, and breakdown
        """
        try:
            client = SHIPClient(
                base_url=self.base_url,
                api_key=self.api_key or None,
                timeout=self.timeout,
            )
            response = client.score(repo)

            result = {
                "repo": repo,
                "ship_score": response.get("score"),
                "grade": response.get("grade"),
                "breakdown": response.get("breakdown", {}),
                "recommendation": _grade_recommendation(response.get("grade", "")),
            }
            return json.dumps(result, indent=2)

        except Exception as e:
            # Antifragile: return degraded response, never crash the agent
            return json.dumps({
                "repo": repo,
                "ship_score": None,
                "grade": "UNKNOWN",
                "error": str(e),
                "fallback": True,
                "message": "Score unavailable. Proceed with caution -- manual review recommended.",
            }, indent=2)


class SHIPDetectTool(BaseTool):
    """
    Detect whether source code is AI-generated.

    Analyzes code patterns (AST features, n-grams, style markers) to determine
    the probability that code was written by an AI tool. Use this to audit
    codebases or verify code provenance.

    Example:
        tool = SHIPDetectTool()
        result = tool._run(code="def hello(): print('world')", language="python")
    """

    name: str = "SHIP Detect"
    description: str = (
        "Detect whether source code is AI-generated. "
        "Analyzes code patterns to determine AI-generation probability. "
        "Input: source code and programming language. "
        "Output: AI probability (0-1), is_ai_generated flag, and feature analysis."
    )
    args_schema: Type[BaseModel] = DetectInput

    # Client configuration
    base_url: str = DEFAULT_BASE_URL
    api_key: str = ""
    timeout: float = DEFAULT_TIMEOUT

    def _run(self, code: str, language: str = "python", **kwargs: Any) -> str:
        """
        Detect if code is AI-generated.

        Args:
            code: Source code to analyze
            language: Programming language of the code

        Returns:
            JSON string with AI probability and analysis details
        """
        try:
            client = SHIPClient(
                base_url=self.base_url,
                api_key=self.api_key or None,
                timeout=self.timeout,
            )
            response = client.detect(code, language)

            result = {
                "ai_probability": response.get("ai_probability"),
                "is_ai_generated": response.get("is_ai_generated"),
                "confidence": response.get("confidence"),
                "language": language,
                "features_analyzed": response.get("features_analyzed"),
                "interpretation": _detection_interpretation(
                    response.get("ai_probability", 0)
                ),
            }
            return json.dumps(result, indent=2)

        except Exception as e:
            return json.dumps({
                "ai_probability": None,
                "is_ai_generated": None,
                "error": str(e),
                "fallback": True,
                "message": "Detection unavailable. Cannot determine code provenance.",
            }, indent=2)


class SHIPHealthTool(BaseTool):
    """
    Check SHIP API health status.

    Use before batch operations to verify API availability. Returns the
    current health status, version, and whether scoring/detection services
    are operational.

    Example:
        tool = SHIPHealthTool()
        result = tool._run()
    """

    name: str = "SHIP Health"
    description: str = (
        "Check SHIP API availability and health status. "
        "Use before batch operations to verify the API is operational. "
        "No input required. Output: health status and version."
    )

    # Client configuration
    base_url: str = DEFAULT_BASE_URL
    api_key: str = ""
    timeout: float = DEFAULT_TIMEOUT

    def _run(self, **kwargs: Any) -> str:
        """
        Check API health.

        Returns:
            JSON string with health status
        """
        try:
            client = SHIPClient(
                base_url=self.base_url,
                api_key=self.api_key or None,
                timeout=self.timeout,
            )
            response = client.health()

            return json.dumps({
                "status": "healthy",
                "version": response.get("version", "unknown"),
                "message": "SHIP API is available and operational.",
            }, indent=2)

        except Exception as e:
            return json.dumps({
                "status": "unhealthy",
                "error": str(e),
                "message": "SHIP API is unavailable. Tools will return fallback responses.",
            }, indent=2)


def _grade_recommendation(grade: str) -> str:
    """Return a human-readable recommendation based on SHIP grade."""
    recommendations = {
        "A+": "Exceptional reliability (95%+). Ship with high confidence.",
        "A": "Reliable (85-94%). Safe to proceed.",
        "B": "Good (70-84%). Minor risks -- review flagged areas.",
        "C": "Fair (50-69%). Proceed with caution, add extra tests.",
        "D": "Poor (30-49%). High risk -- consider rewriting or manual review.",
        "F": "Unreliable (<30%). Likely to fail -- do not ship without major revision.",
    }
    return recommendations.get(grade, "Unknown grade. Manual review recommended.")


def _detection_interpretation(probability: float) -> str:
    """Return a human-readable interpretation of AI detection probability."""
    if probability >= 0.9:
        return "Very likely AI-generated (90%+). Strong AI code patterns detected."
    elif probability >= 0.7:
        return "Likely AI-generated (70-89%). Significant AI markers present."
    elif probability >= 0.5:
        return "Possibly AI-generated (50-69%). Some AI patterns detected."
    elif probability >= 0.3:
        return "Unlikely AI-generated (30-49%). Few AI markers."
    else:
        return "Very unlikely AI-generated (<30%). Appears human-written."
