"""
Webhook management routes.
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from ...shared.config.database import get_db
from ...shared.config.logging_config import get_logger
from ...security.middleware.auth import get_current_user, authorize_roles
from ...auth.models.user import User
from ..services.webhook_service import webhook_service
from ..models.webhook import Webhook, WebhookDelivery, WebhookEventType, WebhookStatus
from ...shared.utils.response_helpers import success_response
from pydantic import BaseModel, HttpUrl

logger = get_logger(__name__)
router = APIRouter(prefix='/webhooks', tags=['webhooks'])

class CreateWebhookRequest(BaseModel):
    name: str
    url: str
    events: List[str]
    description: Optional[str] = None
    retry_count: int = 3
    timeout_seconds: int = 30

@router.post('/')
async def create_webhook(
    webhook_data: CreateWebhookRequest,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Create a new webhook."""
    try:
        webhook = webhook_service.create_webhook(
            db=db,
            name=webhook_data.name,
            url=webhook_data.url,
            events=webhook_data.events,
            created_by=current_user.id,
            description=webhook_data.description,
            retry_count=webhook_data.retry_count,
            timeout_seconds=webhook_data.timeout_seconds
        )
        
        return success_response(
            data={'webhook': {
                'id': webhook.id,
                'name': webhook.name,
                'url': webhook.url,
                'events': webhook.events,
                'status': webhook.status.value,
                'secret': webhook.secret  # Return secret only on creation
            }},
            message='Webhook created successfully'
        )
    except Exception as e:
        logger.error(f'Error creating webhook: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/')
async def get_webhooks(
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Get all webhooks."""
    try:
        from sqlalchemy.orm import noload
        # Explicitly prevent relationship loading which might be causing the SQL error
        webhooks = db.query(Webhook).options(noload(Webhook.creator)).order_by(Webhook.created_at.desc()).all()
        
        result = []
        for w in webhooks:
            try:
                result.append({
                    'id': w.id,
                    'name': w.name,
                    'url': w.url,
                    'events': w.events if w.events else [],
                    'status': w.status.value if w.status else 'inactive',
                    'created_at': w.created_at.isoformat() if w.created_at else None,
                    'updated_at': w.updated_at.isoformat() if w.updated_at else None,
                    'description': w.description,
                    'retry_count': w.retry_count,
                    'timeout_seconds': w.timeout_seconds
                })
            except Exception as e:
                logger.error(f'Error serializing webhook {w.id}: {str(e)}', exc_info=True)
                continue
        
        return success_response(data={'webhooks': result})
    except Exception as e:
        logger.error(f'Error getting webhooks: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/{webhook_id}/deliveries')
async def get_webhook_deliveries(
    webhook_id: int,
    page: int = Query(1, ge=1),
    limit: int = Query(50, ge=1, le=100),
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Get webhook delivery history."""
    try:
        offset = (page - 1) * limit
        deliveries = db.query(WebhookDelivery).filter(
            WebhookDelivery.webhook_id == webhook_id
        ).order_by(WebhookDelivery.created_at.desc()).offset(offset).limit(limit).all()
        
        total = db.query(WebhookDelivery).filter(
            WebhookDelivery.webhook_id == webhook_id
        ).count()
        
        return success_response(data={
            'deliveries': [{
                'id': d.id,
                'event_type': d.event_type,
                'status': d.status.value,
                'response_status': d.response_status,
                'attempt_count': d.attempt_count,
                'created_at': d.created_at.isoformat() if d.created_at else None,
                'delivered_at': d.delivered_at.isoformat() if d.delivered_at else None
            } for d in deliveries],
            'pagination': {
                'page': page,
                'limit': limit,
                'total': total,
                'total_pages': (total + limit - 1) // limit
            }
        })
    except Exception as e:
        logger.error(f'Error getting webhook deliveries: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

class UpdateWebhookRequest(BaseModel):
    name: Optional[str] = None
    url: Optional[str] = None
    events: Optional[List[str]] = None
    description: Optional[str] = None
    status: Optional[str] = None
    retry_count: Optional[int] = None
    timeout_seconds: Optional[int] = None

@router.put('/{webhook_id}')
async def update_webhook(
    webhook_id: int,
    webhook_data: UpdateWebhookRequest,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Update a webhook."""
    try:
        status_enum = None
        if webhook_data.status:
            try:
                status_enum = WebhookStatus(webhook_data.status)
            except ValueError:
                raise HTTPException(status_code=400, detail=f'Invalid status: {webhook_data.status}')
        
        webhook = webhook_service.update_webhook(
            db=db,
            webhook_id=webhook_id,
            name=webhook_data.name,
            url=webhook_data.url,
            events=webhook_data.events,
            description=webhook_data.description,
            status=status_enum,
            retry_count=webhook_data.retry_count,
            timeout_seconds=webhook_data.timeout_seconds
        )
        
        if not webhook:
            raise HTTPException(status_code=404, detail='Webhook not found')
        
        return success_response(
            data={'webhook': {
                'id': webhook.id,
                'name': webhook.name,
                'url': webhook.url,
                'events': webhook.events,
                'status': webhook.status.value,
                'created_at': webhook.created_at.isoformat() if webhook.created_at else None
            }},
            message='Webhook updated successfully'
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f'Error updating webhook: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/{webhook_id}')
async def delete_webhook(
    webhook_id: int,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Delete a webhook."""
    try:
        success = webhook_service.delete_webhook(db=db, webhook_id=webhook_id)
        if not success:
            raise HTTPException(status_code=404, detail='Webhook not found')
        
        return success_response(message='Webhook deleted successfully')
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f'Error deleting webhook: {str(e)}', exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

