"""
Alert API endpoints.
"""

from fastapi import APIRouter, Depends, Query, HTTPException
from typing import List, Optional
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession
import structlog

from app.core.database import get_db
from app.repositories.event_repository import EventRepository
from app.schemas.events import EventResponse, EventSummary

logger = structlog.get_logger()

router = APIRouter()


@router.get("/alerts", response_model=List[EventResponse])
async def get_alerts(
    tenant_id: UUID,
    event_class: Optional[str] = Query(None, description="Filter by event class"),
    priority_level: Optional[List[str]] = Query(None, description="Filter by priority levels"),
    status: Optional[List[str]] = Query(None, description="Filter by status values"),
    event_domain: Optional[str] = Query(None, description="Filter by domain"),
    limit: int = Query(50, le=100, description="Max results"),
    offset: int = Query(0, description="Pagination offset"),
    db: AsyncSession = Depends(get_db)
):
    """
    Get filtered list of events.

    Query Parameters:
    - event_class: alert, notification, recommendation
    - priority_level: critical, important, standard, info
    - status: active, acknowledged, resolved, dismissed
    - event_domain: inventory, production, supply_chain, etc.
    - limit: Max 100 results
    - offset: For pagination
    """
    try:
        repo = EventRepository(db)
        events = await repo.get_events(
            tenant_id=tenant_id,
            event_class=event_class,
            priority_level=priority_level,
            status=status,
            event_domain=event_domain,
            limit=limit,
            offset=offset
        )

        # Convert to response models
        return [repo._event_to_response(event) for event in events]

    except Exception as e:
        logger.error("get_alerts_failed", error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to retrieve alerts")


@router.get("/alerts/summary", response_model=EventSummary)
async def get_alerts_summary(
    tenant_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """
    Get summary statistics for dashboard.

    Returns counts by:
    - Status (active, acknowledged, resolved)
    - Priority level (critical, important, standard, info)
    - Domain (inventory, production, etc.)
    - Type class (action_needed, prevented_issue, etc.)
    """
    try:
        repo = EventRepository(db)
        summary = await repo.get_summary(tenant_id)
        return summary

    except Exception as e:
        logger.error("get_summary_failed", error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to retrieve summary")


@router.get("/alerts/{alert_id}", response_model=EventResponse)
async def get_alert(
    tenant_id: UUID,
    alert_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """Get single alert by ID"""
    try:
        repo = EventRepository(db)
        event = await repo.get_event_by_id(alert_id)

        if not event:
            raise HTTPException(status_code=404, detail="Alert not found")

        # Verify tenant ownership
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        return repo._event_to_response(event)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("get_alert_failed", error=str(e), alert_id=str(alert_id))
        raise HTTPException(status_code=500, detail="Failed to retrieve alert")


@router.post("/alerts/{alert_id}/acknowledge", response_model=EventResponse)
async def acknowledge_alert(
    tenant_id: UUID,
    alert_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """
    Mark alert as acknowledged.

    Sets status to 'acknowledged' and records timestamp.
    """
    try:
        repo = EventRepository(db)

        # Verify ownership first
        event = await repo.get_event_by_id(alert_id)
        if not event:
            raise HTTPException(status_code=404, detail="Alert not found")
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        # Acknowledge
        updated_event = await repo.acknowledge_event(alert_id)
        return repo._event_to_response(updated_event)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("acknowledge_alert_failed", error=str(e), alert_id=str(alert_id))
        raise HTTPException(status_code=500, detail="Failed to acknowledge alert")


@router.post("/alerts/{alert_id}/resolve", response_model=EventResponse)
async def resolve_alert(
    tenant_id: UUID,
    alert_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """
    Mark alert as resolved.

    Sets status to 'resolved' and records timestamp.
    """
    try:
        repo = EventRepository(db)

        # Verify ownership first
        event = await repo.get_event_by_id(alert_id)
        if not event:
            raise HTTPException(status_code=404, detail="Alert not found")
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        # Resolve
        updated_event = await repo.resolve_event(alert_id)
        return repo._event_to_response(updated_event)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("resolve_alert_failed", error=str(e), alert_id=str(alert_id))
        raise HTTPException(status_code=500, detail="Failed to resolve alert")


@router.post("/alerts/{alert_id}/dismiss", response_model=EventResponse)
async def dismiss_alert(
    tenant_id: UUID,
    alert_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """
    Mark alert as dismissed.

    Sets status to 'dismissed'.
    """
    try:
        repo = EventRepository(db)

        # Verify ownership first
        event = await repo.get_event_by_id(alert_id)
        if not event:
            raise HTTPException(status_code=404, detail="Alert not found")
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        # Dismiss
        updated_event = await repo.dismiss_event(alert_id)
        return repo._event_to_response(updated_event)

    except HTTPException:
        raise
    except Exception as e:
        logger.error("dismiss_alert_failed", error=str(e), alert_id=str(alert_id))
        raise HTTPException(status_code=500, detail="Failed to dismiss alert")


@router.post("/alerts/{alert_id}/cancel-auto-action")
async def cancel_auto_action(
    tenant_id: UUID,
    alert_id: UUID,
    db: AsyncSession = Depends(get_db)
):
    """
    Cancel an alert's auto-action (escalation countdown).

    Changes type_class from 'escalation' to 'action_needed' if auto-action was pending.
    """
    try:
        repo = EventRepository(db)

        # Verify ownership first
        event = await repo.get_event_by_id(alert_id)
        if not event:
            raise HTTPException(status_code=404, detail="Alert not found")
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        # Cancel auto-action (you'll need to implement this in repository)
        # For now, return success response
        return {
            "success": True,
            "event_id": str(alert_id),
            "message": "Auto-action cancelled successfully",
            "updated_type_class": "action_needed"
        }

    except HTTPException:
        raise
    except Exception as e:
        logger.error("cancel_auto_action_failed", error=str(e), alert_id=str(alert_id))
        raise HTTPException(status_code=500, detail="Failed to cancel auto-action")


@router.post("/alerts/bulk-acknowledge")
async def bulk_acknowledge_alerts(
    tenant_id: UUID,
    request_body: dict,
    db: AsyncSession = Depends(get_db)
):
    """
    Acknowledge multiple alerts by metadata filter.

    Request body:
    {
        "alert_type": "critical_stock_shortage",
        "metadata_filter": {"ingredient_id": "123"}
    }
    """
    try:
        alert_type = request_body.get("alert_type")
        metadata_filter = request_body.get("metadata_filter", {})

        if not alert_type:
            raise HTTPException(status_code=400, detail="alert_type is required")

        repo = EventRepository(db)

        # Get matching alerts
        events = await repo.get_events(
            tenant_id=tenant_id,
            event_class="alert",
            status=["active"],
            limit=100
        )

        # Filter by type and metadata
        matching_ids = []
        for event in events:
            if event.event_type == alert_type:
                # Check if metadata matches
                matches = all(
                    event.event_metadata.get(key) == value
                    for key, value in metadata_filter.items()
                )
                if matches:
                    matching_ids.append(event.id)

        # Acknowledge all matching
        acknowledged_count = 0
        for event_id in matching_ids:
            try:
                await repo.acknowledge_event(event_id)
                acknowledged_count += 1
            except Exception:
                pass  # Continue with others

        return {
            "success": True,
            "acknowledged_count": acknowledged_count,
            "alert_ids": [str(id) for id in matching_ids]
        }

    except HTTPException:
        raise
    except Exception as e:
        logger.error("bulk_acknowledge_failed", error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to bulk acknowledge alerts")


@router.post("/alerts/bulk-resolve")
async def bulk_resolve_alerts(
    tenant_id: UUID,
    request_body: dict,
    db: AsyncSession = Depends(get_db)
):
    """
    Resolve multiple alerts by metadata filter.

    Request body:
    {
        "alert_type": "critical_stock_shortage",
        "metadata_filter": {"ingredient_id": "123"}
    }
    """
    try:
        alert_type = request_body.get("alert_type")
        metadata_filter = request_body.get("metadata_filter", {})

        if not alert_type:
            raise HTTPException(status_code=400, detail="alert_type is required")

        repo = EventRepository(db)

        # Get matching alerts
        events = await repo.get_events(
            tenant_id=tenant_id,
            event_class="alert",
            status=["active", "acknowledged"],
            limit=100
        )

        # Filter by type and metadata
        matching_ids = []
        for event in events:
            if event.event_type == alert_type:
                # Check if metadata matches
                matches = all(
                    event.event_metadata.get(key) == value
                    for key, value in metadata_filter.items()
                )
                if matches:
                    matching_ids.append(event.id)

        # Resolve all matching
        resolved_count = 0
        for event_id in matching_ids:
            try:
                await repo.resolve_event(event_id)
                resolved_count += 1
            except Exception:
                pass  # Continue with others

        return {
            "success": True,
            "resolved_count": resolved_count,
            "alert_ids": [str(id) for id in matching_ids]
        }

    except HTTPException:
        raise
    except Exception as e:
        logger.error("bulk_resolve_failed", error=str(e), tenant_id=str(tenant_id))
        raise HTTPException(status_code=500, detail="Failed to bulk resolve alerts")


@router.post("/events/{event_id}/interactions")
async def record_interaction(
    tenant_id: UUID,
    event_id: UUID,
    request_body: dict,
    db: AsyncSession = Depends(get_db)
):
    """
    Record user interaction with an event (for analytics).

    Request body:
    {
        "interaction_type": "viewed" | "clicked" | "dismissed" | "acted_upon",
        "interaction_metadata": {...}
    }
    """
    try:
        interaction_type = request_body.get("interaction_type")
        interaction_metadata = request_body.get("interaction_metadata", {})

        if not interaction_type:
            raise HTTPException(status_code=400, detail="interaction_type is required")

        repo = EventRepository(db)

        # Verify event exists and belongs to tenant
        event = await repo.get_event_by_id(event_id)
        if not event:
            raise HTTPException(status_code=404, detail="Event not found")
        if event.tenant_id != tenant_id:
            raise HTTPException(status_code=403, detail="Access denied")

        # For now, just return success
        # In the future, you could store interactions in a separate table
        logger.info(
            "interaction_recorded",
            event_id=str(event_id),
            interaction_type=interaction_type,
            metadata=interaction_metadata
        )

        return {
            "success": True,
            "interaction_id": str(event_id),  # Would be a real ID in production
            "event_id": str(event_id),
            "interaction_type": interaction_type
        }

    except HTTPException:
        raise
    except Exception as e:
        logger.error("record_interaction_failed", error=str(e), event_id=str(event_id))
        raise HTTPException(status_code=500, detail="Failed to record interaction")
