"""
POST /api/v1/analyze

The core endpoint. Deliberately does NOT run models inline — it checks
the cache, and on a miss, queues a Celery task and returns immediately
with a task_id. This is what lets the web tier stay fast and responsive
under load regardless of how long model inference + LLM calls take.

Accepts either a logged-in customer (JWT, via the SaaS dashboard) or a
service API key (machine-to-machine integration) — see
app/core/dual_auth.py. Results from a logged-in user are attributed to
their account (AnalysisRecord.user_id) so the dashboard can show their
history; API-key calls remain anonymous as before.

See GET /api/v1/tasks/{task_id} for how the client retrieves the result.
"""

import uuid

from fastapi import APIRouter, Depends, Request

from app.core.config import get_settings
from app.core.dual_auth import AuthContext, get_auth_context
from app.core.logging_config import get_logger
from app.core.security import RedisRateLimiter, get_client_identifier
from app.schemas.request import CropAnalysisRequest, TaskSubmissionResponse
from app.services.cache_service import build_cache_key, cache_service
from app.workers.tasks import run_crop_analysis

router = APIRouter()
settings = get_settings()
logger = get_logger(__name__)


@router.post("/analyze", response_model=TaskSubmissionResponse, status_code=202)
async def analyze_crop(
    payload: CropAnalysisRequest,
    request: Request,
    auth: AuthContext = Depends(get_auth_context),
) -> TaskSubmissionResponse:
    request_id = str(uuid.uuid4())

    identifier = await get_client_identifier(request)
    if cache_service.raw_client is not None:
        limiter = RedisRateLimiter(cache_service.raw_client, settings.RATE_LIMIT_PER_MINUTE)
        await limiter.check(identifier)

    cache_key = build_cache_key(payload.location, payload.crop, payload.month, settings.MODEL_VERSION)
    cached_result = await cache_service.get(cache_key)

    if cached_result is not None:
        logger.info(f"Cache hit for {payload.crop}/{payload.location}/{payload.month}")
        # Cached results are returned through the same task-id/poll-url
        # contract as a fresh computation, so the client never needs two
        # code paths. We store the cached payload under a synthetic
        # "cached-<uuid>" task id with a short TTL — the polling endpoint
        # (tasks.py) recognizes this prefix and serves it directly from
        # Redis instead of asking Celery for a result, since no real
        # Celery task was ever created for this request.
        #
        # Note: a cache hit does NOT write a fresh AnalysisRecord row for
        # this user — the original computation already has one. This
        # matches the cache's purpose (avoid recomputation), though it
        # means a user's "history" view should ideally also consider
        # cache hits if exact per-request audit trail matters later.
        cached_result["request_id"] = request_id
        cached_result["cached"] = True

        synthetic_task_id = f"cached-{request_id}"
        await cache_service.set(f"task_result:{synthetic_task_id}", cached_result, ttl_seconds=300)
        return TaskSubmissionResponse(
            task_id=synthetic_task_id,
            status="completed",
            poll_url=f"{settings.API_V1_PREFIX}/tasks/{synthetic_task_id}",
        )

    client_host = request.client.host if request.client else None
    task = run_crop_analysis.delay(
        request_id=request_id,
        district=payload.location,
        crop=payload.crop,
        month=payload.month,
        api_key_prefix=auth.api_key[:12] if auth.api_key else None,
        client_ip=client_host,
        user_id=auth.user_id,
        crop_plan_id=payload.crop_plan_id,
    )

    logger.info(
        f"Queued analysis task {task.id} for request_id={request_id} "
        f"crop={payload.crop} district={payload.location} month={payload.month} "
        f"auth_type={auth.auth_type} user_id={auth.user_id}"
    )

    return TaskSubmissionResponse(
        task_id=task.id,
        status="queued",
        poll_url=f"{settings.API_V1_PREFIX}/tasks/{task.id}",
    )
