"""
Pramana REST API — FastAPI server for verification-as-a-service.

Endpoints:
    POST /verify          — Full pipeline (nyaya + vedic + strategy)
    POST /verify/quick    — Constraint-only (vedic engine)
    POST /verify/claim    — Evidence-only (nyaya gate)
    POST /verify/action   — Strategy-only (arthashastra gate)
    POST /verify/llm      — LLM output verification
    GET  /health          — Health check
    GET  /sutras          — List available sutras

Run:
    python -m pramana.api.server
    # or: uvicorn pramana.api.server:app --host 0.0.0.0 --port 8108
"""

import json
import os
import sys
from datetime import datetime

# Check for FastAPI availability
try:
    from fastapi import FastAPI, HTTPException, Header, Depends
    from fastapi.middleware.cors import CORSMiddleware
    from pydantic import BaseModel
    from typing import Optional
    HAS_FASTAPI = True
except ImportError:
    HAS_FASTAPI = False

from pramana.core.engine import Pramana, VerificationResult
from pramana.core.nyaya import Evidence, PramanaType
from pramana.core.vedic import Sutra
from pramana.core.arthashastra import StrategicContext
from pramana.constraints.agent_safety import verify_llm_output, verify_agent_action


def create_app() -> "FastAPI":
    if not HAS_FASTAPI:
        raise ImportError(
            "FastAPI not installed. Run: pip install fastapi uvicorn"
        )

    app = FastAPI(
        title="Pramana Engine",
        description="Vedic Verification for AI — "
                    "Epistemologically-grounded constraint verification",
        version="0.1.0",
    )

    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_methods=["*"],
        allow_headers=["*"],
    )

    engine = Pramana()
    API_KEY = os.environ.get("PRAMANA_API_KEY", "")

    def check_auth(api_key: str = Header(None, alias="x-api-key")):
        if API_KEY and api_key != API_KEY:
            raise HTTPException(401, "Invalid API key")

    auth_dep = [Depends(check_auth)] if API_KEY else []

    # --- Models ---

    class VerifyRequest(BaseModel):
        claim: str = ""
        evidence: list = []
        constraints: dict = {}
        data: dict = {}
        context: Optional[dict] = None
        sutras: Optional[list] = None
        layers: Optional[list] = None

    class QuickVerifyRequest(BaseModel):
        data: dict
        constraints: dict
        sutras: Optional[list] = None

    class ClaimRequest(BaseModel):
        claim: str
        evidence: list
        constraints: dict = {}

    class ActionRequest(BaseModel):
        action_type: str
        action_params: dict = {}
        agent_context: dict = {}
        evidence: list = []

    class LLMVerifyRequest(BaseModel):
        output: str
        expected_format: Optional[str] = None
        max_length: Optional[int] = None
        required_fields: Optional[list] = None
        banned_patterns: Optional[list] = None

    # --- Endpoints ---

    @app.get("/health")
    def health():
        return {
            "status": "healthy",
            "engine": "pramana",
            "version": "0.1.0",
            "timestamp": datetime.utcnow().isoformat() + "Z",
        }

    @app.get("/sutras")
    def list_sutras():
        return {
            "sutras": [
                {
                    "name": s.name,
                    "value": s.value,
                    "description": _sutra_descriptions.get(s.name, "")
                }
                for s in Sutra
            ]
        }

    @app.post("/verify", dependencies=auth_dep)
    def verify(req: VerifyRequest):
        # Convert evidence dicts to Evidence objects
        evidence_objs = _parse_evidence(req.evidence)

        # Convert context dict to StrategicContext
        ctx = None
        if req.context:
            ctx = StrategicContext(**{
                k: v for k, v in req.context.items()
                if k in StrategicContext.__dataclass_fields__
            })

        # Convert sutra names to Sutra enums
        sutra_enums = None
        if req.sutras:
            sutra_enums = [
                s for s in Sutra if s.value in req.sutras or s.name in req.sutras
            ]

        result = engine.verify(
            claim=req.claim,
            evidence=evidence_objs,
            constraints=req.constraints,
            data=req.data,
            context=ctx,
            sutras=sutra_enums,
            layers=req.layers,
        )
        return result.to_dict()

    @app.post("/verify/quick", dependencies=auth_dep)
    def verify_quick(req: QuickVerifyRequest):
        sutra_enums = None
        if req.sutras:
            sutra_enums = [
                s for s in Sutra if s.value in req.sutras or s.name in req.sutras
            ]
        result = engine.verify_quick(req.data, req.constraints, sutra_enums)
        return result.to_dict()

    @app.post("/verify/claim", dependencies=auth_dep)
    def verify_claim(req: ClaimRequest):
        evidence_objs = _parse_evidence(req.evidence)
        result = engine.verify_claim(req.claim, evidence_objs, req.constraints)
        return result.to_dict()

    @app.post("/verify/action", dependencies=auth_dep)
    def verify_action(req: ActionRequest):
        evidence_objs = _parse_evidence(req.evidence)
        result = verify_agent_action(
            action_type=req.action_type,
            action_params=req.action_params,
            agent_context=req.agent_context,
            evidence=evidence_objs,
        )
        return result.to_dict()

    @app.post("/verify/llm", dependencies=auth_dep)
    def verify_llm(req: LLMVerifyRequest):
        result = verify_llm_output(
            output=req.output,
            expected_format=req.expected_format,
            max_length=req.max_length,
            required_fields=req.required_fields,
            banned_patterns=req.banned_patterns,
        )
        return result.to_dict()

    return app


def _parse_evidence(evidence_list: list) -> list:
    """Convert evidence dicts from API to Evidence objects."""
    objs = []
    pramana_map = {
        "pratyaksha": PramanaType.PRATYAKSHA,
        "anumana": PramanaType.ANUMANA,
        "upamana": PramanaType.UPAMANA,
        "shabda": PramanaType.SHABDA,
        "direct": PramanaType.PRATYAKSHA,
        "inference": PramanaType.ANUMANA,
        "analogy": PramanaType.UPAMANA,
        "testimony": PramanaType.SHABDA,
    }
    for e in evidence_list:
        if isinstance(e, Evidence):
            objs.append(e)
            continue
        if isinstance(e, dict):
            pt = pramana_map.get(
                e.get("pramana_type", "shabda").lower(),
                PramanaType.SHABDA
            )
            objs.append(Evidence(
                value=e.get("value"),
                pramana_type=pt,
                source=e.get("source", ""),
                reliability=e.get("reliability", 0.7),
                metadata=e.get("metadata", {}),
            ))
    return objs


_sutra_descriptions = {
    "EKADHIKENA": "Sequential constraint — each step builds on the last",
    "NIKHILAM": "Complement verification — check from the inverse",
    "URDHVA_TIRYAK": "Multi-dimensional simultaneous check",
    "PARAVARTYA": "Transform constraints to simpler equivalent form",
    "SHUNYAM": "Equilibrium / balance verification",
    "ANURUPYENA": "Scale invariance — proportional relationships hold",
    "SANKALANA": "Additive consistency — parts must sum to whole",
    "PURANAPURANA": "Completeness check — all required components present",
    "CHALANA": "Delta analysis — changes must be within bounds",
    "YAVADUNAM": "Gap analysis — measure and bound the deficit",
    "VYASHTI": "Compositional integrity — parts consistent with whole",
    "SHESHANYANKENA": "Residual check — modular arithmetic verification",
    "SOPAANTYA": "Boundary verification — edge cases valid",
    "EKANYUNENA": "Decremental constraint — diminishing returns check",
    "GUNITASAMUCHYA": "Distributive consistency — aggregation preserves truth",
    "GUNAKA": "Factorization integrity — decomposition is valid",
}


# Create app instance for uvicorn
app = create_app() if HAS_FASTAPI else None


if __name__ == "__main__":
    if not HAS_FASTAPI:
        print("Install FastAPI: pip install fastapi uvicorn")
        sys.exit(1)
    import uvicorn
    port = int(os.environ.get("PRAMANA_PORT", "8108"))
    uvicorn.run(app, host="0.0.0.0", port=port)
