"""
Retrieval Strategy API Endpoints.
[AC-AISVC-RES-01~15] API for strategy management and configuration.

Endpoints:
- GET /strategy/retrieval/current - Get current strategy configuration
- POST /strategy/retrieval/switch - Switch strategy configuration
- POST /strategy/retrieval/validate - Validate strategy configuration
- POST /strategy/retrieval/rollback - Rollback to default strategy
"""

import logging
from typing import Any

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_session
from app.core.tenant import get_tenant_id
from app.services.retrieval.routing_config import (
    RagRuntimeMode,
    StrategyType,
    RoutingConfig,
)
from app.services.retrieval.strategy_router import (
    get_strategy_router,
    RollbackRecord,
)
from app.services.retrieval.mode_router import get_mode_router

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/strategy/retrieval", tags=["Retrieval Strategy"])


class RoutingConfigRequest(BaseModel):
    """Request model for routing configuration."""
    enabled: bool | None = Field(default=None, description="Enable strategy routing")
    strategy: StrategyType | None = Field(default=None, description="Retrieval strategy")
    grayscale_percentage: float | None = Field(default=None, ge=0.0, le=1.0, description="Grayscale percentage")
    grayscale_allowlist: list[str] | None = Field(default=None, description="Grayscale allowlist")
    rag_runtime_mode: RagRuntimeMode | None = Field(default=None, description="RAG runtime mode")
    react_trigger_confidence_threshold: float | None = Field(default=None, ge=0.0, le=1.0)
    react_trigger_complexity_score: float | None = Field(default=None, ge=0.0, le=1.0)
    react_max_steps: int | None = Field(default=None, ge=3, le=10)
    direct_fallback_on_low_confidence: bool | None = Field(default=None)
    direct_fallback_confidence_threshold: float | None = Field(default=None, ge=0.0, le=1.0)
    performance_budget_ms: int | None = Field(default=None, ge=1000)
    performance_degradation_threshold: float | None = Field(default=None, ge=0.0, le=1.0)


class RoutingConfigResponse(BaseModel):
    """Response model for routing configuration."""
    enabled: bool
    strategy: StrategyType
    grayscale_percentage: float
    grayscale_allowlist: list[str]
    rag_runtime_mode: RagRuntimeMode
    react_trigger_confidence_threshold: float
    react_trigger_complexity_score: float
    react_max_steps: int
    direct_fallback_on_low_confidence: bool
    direct_fallback_confidence_threshold: float
    performance_budget_ms: int
    performance_degradation_threshold: float


class ValidationResponse(BaseModel):
    """Response model for configuration validation."""
    is_valid: bool
    errors: list[str]
    warnings: list[str] = Field(default_factory=list)


class RollbackRequest(BaseModel):
    """Request model for strategy rollback."""
    reason: str = Field(..., description="Reason for rollback")
    tenant_id: str | None = Field(default=None, description="Optional tenant ID for audit")


class RollbackResponse(BaseModel):
    """Response model for strategy rollback."""
    success: bool
    previous_strategy: StrategyType
    current_strategy: StrategyType
    reason: str
    rollback_records: list[dict[str, Any]] = Field(default_factory=list)


class RollbackRecordResponse(BaseModel):
    """Response model for rollback record."""
    timestamp: float
    from_strategy: StrategyType
    to_strategy: StrategyType
    reason: str
    tenant_id: str | None
    request_id: str | None


class CurrentStrategyResponse(BaseModel):
    """Response model for current strategy."""
    config: RoutingConfigResponse
    current_strategy: StrategyType
    rollback_records: list[RollbackRecordResponse] = Field(default_factory=list)


@router.get(
    "/current",
    operation_id="getCurrentRetrievalStrategy",
    summary="Get current retrieval strategy configuration",
    description="[AC-AISVC-RES-01] Returns the current strategy configuration and recent rollback records.",
    response_model=CurrentStrategyResponse,
)
async def get_current_strategy() -> CurrentStrategyResponse:
    """
    [AC-AISVC-RES-01] Get current retrieval strategy configuration.
    """
    strategy_router = get_strategy_router()
    config = strategy_router.config
    rollback_records = strategy_router.get_rollback_records(limit=5)
    
    return CurrentStrategyResponse(
        config=RoutingConfigResponse(
            enabled=config.enabled,
            strategy=config.strategy,
            grayscale_percentage=config.grayscale_percentage,
            grayscale_allowlist=config.grayscale_allowlist,
            rag_runtime_mode=config.rag_runtime_mode,
            react_trigger_confidence_threshold=config.react_trigger_confidence_threshold,
            react_trigger_complexity_score=config.react_trigger_complexity_score,
            react_max_steps=config.react_max_steps,
            direct_fallback_on_low_confidence=config.direct_fallback_on_low_confidence,
            direct_fallback_confidence_threshold=config.direct_fallback_confidence_threshold,
            performance_budget_ms=config.performance_budget_ms,
            performance_degradation_threshold=config.performance_degradation_threshold,
        ),
        current_strategy=strategy_router.current_strategy,
        rollback_records=[
            RollbackRecordResponse(
                timestamp=r.timestamp,
                from_strategy=r.from_strategy,
                to_strategy=r.to_strategy,
                reason=r.reason,
                tenant_id=r.tenant_id,
                request_id=r.request_id,
            )
            for r in rollback_records
        ],
    )


@router.post(
    "/switch",
    operation_id="switchRetrievalStrategy",
    summary="Switch retrieval strategy configuration",
    description="[AC-AISVC-RES-02, AC-AISVC-RES-03] Update strategy configuration with hot reload support.",
    response_model=RoutingConfigResponse,
)
async def switch_strategy(
    request: RoutingConfigRequest,
    session: AsyncSession = Depends(get_session),
) -> RoutingConfigResponse:
    """
    [AC-AISVC-RES-02, AC-AISVC-RES-03, AC-AISVC-RES-15] 
    Switch retrieval strategy configuration.
    
    Supports:
    - Strategy selection (default/enhanced)
    - Grayscale release (percentage/allowlist)
    - Mode selection (direct/react/auto)
    - Hot reload of routing parameters
    """
    strategy_router = get_strategy_router()
    mode_router = get_mode_router()
    current_config = strategy_router.config
    
    new_config = RoutingConfig(
        enabled=request.enabled if request.enabled is not None else current_config.enabled,
        strategy=request.strategy if request.strategy is not None else current_config.strategy,
        grayscale_percentage=request.grayscale_percentage if request.grayscale_percentage is not None else current_config.grayscale_percentage,
        grayscale_allowlist=request.grayscale_allowlist if request.grayscale_allowlist is not None else current_config.grayscale_allowlist,
        rag_runtime_mode=request.rag_runtime_mode if request.rag_runtime_mode is not None else current_config.rag_runtime_mode,
        react_trigger_confidence_threshold=request.react_trigger_confidence_threshold if request.react_trigger_confidence_threshold is not None else current_config.react_trigger_confidence_threshold,
        react_trigger_complexity_score=request.react_trigger_complexity_score if request.react_trigger_complexity_score is not None else current_config.react_trigger_complexity_score,
        react_max_steps=request.react_max_steps if request.react_max_steps is not None else current_config.react_max_steps,
        direct_fallback_on_low_confidence=request.direct_fallback_on_low_confidence if request.direct_fallback_on_low_confidence is not None else current_config.direct_fallback_on_low_confidence,
        direct_fallback_confidence_threshold=request.direct_fallback_confidence_threshold if request.direct_fallback_confidence_threshold is not None else current_config.direct_fallback_confidence_threshold,
        performance_budget_ms=request.performance_budget_ms if request.performance_budget_ms is not None else current_config.performance_budget_ms,
        performance_degradation_threshold=request.performance_degradation_threshold if request.performance_degradation_threshold is not None else current_config.performance_degradation_threshold,
    )
    
    is_valid, errors = new_config.validate()
    if not is_valid:
        raise HTTPException(
            status_code=400,
            detail={"errors": errors},
        )
    
    strategy_router.update_config(new_config)
    mode_router.update_config(new_config)
    
    logger.info(
        f"[AC-AISVC-RES-02, AC-AISVC-RES-15] Strategy switched: "
        f"strategy={new_config.strategy.value}, mode={new_config.rag_runtime_mode.value}"
    )
    
    return RoutingConfigResponse(
        enabled=new_config.enabled,
        strategy=new_config.strategy,
        grayscale_percentage=new_config.grayscale_percentage,
        grayscale_allowlist=new_config.grayscale_allowlist,
        rag_runtime_mode=new_config.rag_runtime_mode,
        react_trigger_confidence_threshold=new_config.react_trigger_confidence_threshold,
        react_trigger_complexity_score=new_config.react_trigger_complexity_score,
        react_max_steps=new_config.react_max_steps,
        direct_fallback_on_low_confidence=new_config.direct_fallback_on_low_confidence,
        direct_fallback_confidence_threshold=new_config.direct_fallback_confidence_threshold,
        performance_budget_ms=new_config.performance_budget_ms,
        performance_degradation_threshold=new_config.performance_degradation_threshold,
    )


@router.post(
    "/validate",
    operation_id="validateRetrievalStrategy",
    summary="Validate retrieval strategy configuration",
    description="[AC-AISVC-RES-06] Validate strategy configuration for completeness and consistency.",
    response_model=ValidationResponse,
)
async def validate_strategy(
    request: RoutingConfigRequest,
) -> ValidationResponse:
    """
    [AC-AISVC-RES-06] Validate strategy configuration.
    
    Checks:
    - Parameter value ranges
    - Configuration consistency
    - Performance budget constraints
    """
    warnings = []
    
    config = RoutingConfig(
        enabled=request.enabled if request.enabled is not None else True,
        strategy=request.strategy if request.strategy is not None else StrategyType.DEFAULT,
        grayscale_percentage=request.grayscale_percentage if request.grayscale_percentage is not None else 0.0,
        grayscale_allowlist=request.grayscale_allowlist or [],
        rag_runtime_mode=request.rag_runtime_mode if request.rag_runtime_mode is not None else RagRuntimeMode.AUTO,
        react_trigger_confidence_threshold=request.react_trigger_confidence_threshold if request.react_trigger_confidence_threshold is not None else 0.6,
        react_trigger_complexity_score=request.react_trigger_complexity_score if request.react_trigger_complexity_score is not None else 0.5,
        react_max_steps=request.react_max_steps if request.react_max_steps is not None else 5,
        direct_fallback_on_low_confidence=request.direct_fallback_on_low_confidence if request.direct_fallback_on_low_confidence is not None else True,
        direct_fallback_confidence_threshold=request.direct_fallback_confidence_threshold if request.direct_fallback_confidence_threshold is not None else 0.4,
        performance_budget_ms=request.performance_budget_ms if request.performance_budget_ms is not None else 5000,
        performance_degradation_threshold=request.performance_degradation_threshold if request.performance_degradation_threshold is not None else 0.2,
    )
    
    is_valid, errors = config.validate()
    
    if config.grayscale_percentage > 0.5:
        warnings.append("grayscale_percentage > 50% may affect production stability")
    
    if config.react_max_steps > 7:
        warnings.append("react_max_steps > 7 may cause high latency")
    
    if config.direct_fallback_confidence_threshold > config.react_trigger_confidence_threshold:
        warnings.append(
            "direct_fallback_confidence_threshold > react_trigger_confidence_threshold "
            "may cause frequent fallbacks"
        )
    
    if config.performance_budget_ms < 3000:
        warnings.append("performance_budget_ms < 3000ms may be too aggressive for complex queries")
    
    logger.info(
        f"[AC-AISVC-RES-06] Strategy validation: is_valid={is_valid}, "
        f"errors={len(errors)}, warnings={len(warnings)}"
    )
    
    return ValidationResponse(
        is_valid=is_valid,
        errors=errors,
        warnings=warnings,
    )


@router.post(
    "/rollback",
    operation_id="rollbackRetrievalStrategy",
    summary="Rollback to default retrieval strategy",
    description="[AC-AISVC-RES-07] Force rollback to default strategy with audit logging.",
    response_model=RollbackResponse,
)
async def rollback_strategy(
    request: RollbackRequest,
    session: AsyncSession = Depends(get_session),
) -> RollbackResponse:
    """
    [AC-AISVC-RES-07] Rollback to default strategy.
    
    Records the rollback event for audit and monitoring.
    """
    strategy_router = get_strategy_router()
    mode_router = get_mode_router()
    
    previous_strategy = strategy_router.current_strategy
    
    strategy_router.rollback(
        reason=request.reason,
        tenant_id=request.tenant_id,
    )
    
    new_config = RoutingConfig(
        strategy=StrategyType.DEFAULT,
        rag_runtime_mode=RagRuntimeMode.AUTO,
    )
    mode_router.update_config(new_config)
    
    rollback_records = strategy_router.get_rollback_records(limit=5)
    
    logger.info(
        f"[AC-AISVC-RES-07] Strategy rollback: "
        f"from={previous_strategy.value}, to=DEFAULT, reason={request.reason}"
    )
    
    return RollbackResponse(
        success=True,
        previous_strategy=previous_strategy,
        current_strategy=StrategyType.DEFAULT,
        reason=request.reason,
        rollback_records=[
            {
                "timestamp": r.timestamp,
                "from_strategy": r.from_strategy.value,
                "to_strategy": r.to_strategy.value,
                "reason": r.reason,
                "tenant_id": r.tenant_id,
            }
            for r in rollback_records
        ],
    )
