"""Webhook endpoint handlers for Gitea events."""

import logging
from typing import Any

from fastapi import APIRouter, Header, HTTPException, Request
from pydantic import BaseModel, Field
from slowapi import Limiter
from slowapi.util import get_remote_address

from .config import settings
from .security import verify_signature

logger = logging.getLogger(__name__)

router = APIRouter()

# Initialize limiter for this module
limiter = Limiter(key_func=get_remote_address)


class WebhookResponse(BaseModel):
    """Response model for webhook endpoint."""

    status: str = Field(..., description="Status of webhook processing")
    action: str = Field(..., description="Action type from webhook")
    issue_number: int | None = Field(None, description="Issue number if applicable")
    message: str | None = Field(None, description="Additional message")


class GiteaWebhookPayload(BaseModel):
    """Model for Gitea webhook payload."""

    action: str = Field(..., description="Action type (assigned, unassigned, closed, etc.)")
    number: int = Field(..., description="Issue or PR number")
    issue: dict[str, Any] | None = Field(None, description="Issue details")
    repository: dict[str, Any] | None = Field(None, description="Repository details")
    sender: dict[str, Any] | None = Field(None, description="User who triggered event")


@router.post("/webhook/gitea", response_model=WebhookResponse)
@limiter.limit("100/minute")  # Per-IP rate limit: 100 requests per minute
async def handle_gitea_webhook(
    request: Request,
    payload: GiteaWebhookPayload,
    x_gitea_signature: str | None = Header(None, alias="X-Gitea-Signature"),
) -> WebhookResponse:
    """
    Handle Gitea webhook events.

    Verifies HMAC SHA256 signature and routes events to appropriate handlers.

    Args:
        request: FastAPI request object
        payload: Parsed webhook payload
        x_gitea_signature: HMAC signature from Gitea

    Returns:
        WebhookResponse indicating success or failure

    Raises:
        HTTPException: 401 if signature is invalid or missing
    """
    # Get raw request body for signature verification
    body = await request.body()

    # Verify signature
    if not x_gitea_signature or not verify_signature(
        body, x_gitea_signature, settings.gitea_webhook_secret
    ):
        logger.warning(
            "Webhook received with invalid or missing signature",
            extra={"action": payload.action, "issue_number": payload.number},
        )
        raise HTTPException(status_code=401, detail="Invalid or missing signature")

    # Log the event
    logger.info(
        f"Webhook event received: action={payload.action}, issue_number={payload.number}",
        extra={
            "action": payload.action,
            "issue_number": payload.number,
            "repository": payload.repository.get("full_name") if payload.repository else None,
        },
    )

    # Route to appropriate handler based on action
    if payload.action == "assigned":
        return await handle_assigned_event(payload)
    elif payload.action == "unassigned":
        return await handle_unassigned_event(payload)
    elif payload.action == "closed":
        return await handle_closed_event(payload)
    else:
        # Ignore unsupported actions
        logger.debug(f"Ignoring unsupported action: {payload.action}")
        return WebhookResponse(
            status="ignored",
            action=payload.action,
            issue_number=payload.number,
            message=f"Action '{payload.action}' is not supported",
        )


async def handle_assigned_event(payload: GiteaWebhookPayload) -> WebhookResponse:
    """
    Handle issue assigned event.

    Args:
        payload: Webhook payload

    Returns:
        WebhookResponse indicating success
    """
    logger.info(
        f"Issue #{payload.number} assigned",
        extra={
            "issue_number": payload.number,
            "assignee": payload.issue.get("assignee", {}).get("login") if payload.issue else None,
        },
    )

    # TODO: Trigger issue parser and context estimator (issue #158)
    # For now, just log and return success

    return WebhookResponse(
        status="success",
        action="assigned",
        issue_number=payload.number,
        message=f"Issue #{payload.number} assigned event processed",
    )


async def handle_unassigned_event(payload: GiteaWebhookPayload) -> WebhookResponse:
    """
    Handle issue unassigned event.

    Args:
        payload: Webhook payload

    Returns:
        WebhookResponse indicating success
    """
    logger.info(
        f"Issue #{payload.number} unassigned",
        extra={"issue_number": payload.number},
    )

    # TODO: Update coordinator state (issue #159+)
    # For now, just log and return success

    return WebhookResponse(
        status="success",
        action="unassigned",
        issue_number=payload.number,
        message=f"Issue #{payload.number} unassigned event processed",
    )


async def handle_closed_event(payload: GiteaWebhookPayload) -> WebhookResponse:
    """
    Handle issue closed event.

    Args:
        payload: Webhook payload

    Returns:
        WebhookResponse indicating success
    """
    logger.info(
        f"Issue #{payload.number} closed",
        extra={"issue_number": payload.number},
    )

    # TODO: Update coordinator state and cleanup (issue #159+)
    # For now, just log and return success

    return WebhookResponse(
        status="success",
        action="closed",
        issue_number=payload.number,
        message=f"Issue #{payload.number} closed event processed",
    )
