from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session, joinedload
from typing import List
from datetime import datetime
from config.database import get_db
from models.event import Event, EventParticipation, ParticipationStatus
from models.user import User
from models.notification import Notification, NotificationType
from schemas.event import EventCreate, EventUpdate, EventResponse, ParticipationUpdate
from utils.security import get_current_active_user
from utils.email import send_event_notification

router = APIRouter()

@router.post("/", response_model=EventResponse)
async def create_event(
    event_data: EventCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Create a new event."""
    event = Event(
        **event_data.dict(),
        creator_id=current_user.id
    )
    db.add(event)
    db.commit()
    db.refresh(event)
    
    # Create participations for all active users
    users = db.query(User).filter(User.is_active == True).all()
    for user in users:
        participation = EventParticipation(
            event_id=event.id,
            user_id=user.id,
            status=ParticipationStatus.PENDING
        )
        db.add(participation)
        
        # Create notification
        if user.id != current_user.id:
            notification = Notification(
                user_id=user.id,
                type=NotificationType.EVENT_INVITATION,
                title=f"Nouvel événement: {event.title}",
                message=f"{current_user.full_name} a créé un nouvel événement",
                link=f"/events/{event.id}"
            )
            db.add(notification)
            
            # Send email notification (async task would be better)
            try:
                send_event_notification(user.email, event)
            except:
                pass  # Don't fail if email sending fails
    
    db.commit()
    return format_event_response(event, db)

@router.get("/", response_model=List[EventResponse])
async def get_events(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    upcoming: bool = None
):
    """Get all events, optionally filtered by upcoming status."""
    query = db.query(Event).options(joinedload(Event.creator))
    
    if upcoming is True:
        # Only upcoming events
        query = query.filter(Event.date >= datetime.utcnow())
    elif upcoming is False:
        # Only past events
        query = query.filter(Event.date < datetime.utcnow())
    # If upcoming is None, return all events
    
    events = query.order_by(Event.date.desc()).all()
    return [format_event_response(event, db) for event in events]

@router.get("/upcoming", response_model=List[EventResponse])
async def get_upcoming_events(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Get only upcoming events."""
    events = db.query(Event).options(joinedload(Event.creator)).filter(
        Event.date >= datetime.utcnow()
    ).order_by(Event.date).all()
    return [format_event_response(event, db) for event in events]

@router.get("/past", response_model=List[EventResponse])
async def get_past_events(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Get only past events."""
    events = db.query(Event).options(joinedload(Event.creator)).filter(
        Event.date < datetime.utcnow()
    ).order_by(Event.date.desc()).all()
    return [format_event_response(event, db) for event in events]

@router.get("/{event_id}", response_model=EventResponse)
async def get_event(
    event_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Get a specific event."""
    event = db.query(Event).filter(Event.id == event_id).first()
    if not event:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Event not found"
        )
    return format_event_response(event, db)

@router.put("/{event_id}", response_model=EventResponse)
async def update_event(
    event_id: int,
    event_update: EventUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Update an event."""
    event = db.query(Event).filter(Event.id == event_id).first()
    if not event:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Event not found"
        )
    
    if event.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to update this event"
        )
    
    for field, value in event_update.dict(exclude_unset=True).items():
        setattr(event, field, value)
    
    db.commit()
    db.refresh(event)
    return format_event_response(event, db)

@router.delete("/{event_id}")
async def delete_event(
    event_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Delete an event."""
    event = db.query(Event).filter(Event.id == event_id).first()
    if not event:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Event not found"
        )
    
    if event.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to delete this event"
        )
    
    db.delete(event)
    db.commit()
    return {"message": "Event deleted successfully"}

@router.put("/{event_id}/participation", response_model=EventResponse)
async def update_participation(
    event_id: int,
    participation_update: ParticipationUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Update user participation status for an event."""
    participation = db.query(EventParticipation).filter(
        EventParticipation.event_id == event_id,
        EventParticipation.user_id == current_user.id
    ).first()
    
    if not participation:
        # Create new participation if it doesn't exist
        participation = EventParticipation(
            event_id=event_id,
            user_id=current_user.id,
            status=participation_update.status
        )
        db.add(participation)
    else:
        participation.status = participation_update.status
        participation.response_date = datetime.utcnow()
    
    db.commit()
    
    # Update user attendance rate
    update_user_attendance_rate(current_user, db)
    
    event = db.query(Event).filter(Event.id == event_id).first()
    return format_event_response(event, db)

def format_event_response(event: Event, db: Session) -> dict:
    """Format event response with participation counts."""
    participations = []
    present_count = absent_count = maybe_count = pending_count = 0
    
    # Get creator user directly
    creator = db.query(User).filter(User.id == event.creator_id).first()
    
    for p in event.participations:
        user = db.query(User).filter(User.id == p.user_id).first()
        participations.append({
            "user_id": user.id,
            "username": user.username,
            "full_name": user.full_name,
            "avatar_url": user.avatar_url,
            "status": p.status,
            "response_date": p.response_date
        })
        
        if p.status == ParticipationStatus.PRESENT:
            present_count += 1
        elif p.status == ParticipationStatus.ABSENT:
            absent_count += 1
        elif p.status == ParticipationStatus.MAYBE:
            maybe_count += 1
        else:
            pending_count += 1
    
    return {
        "id": event.id,
        "title": event.title,
        "description": event.description,
        "location": event.location,
        "date": event.date,
        "end_date": event.end_date,
        "creator_id": event.creator_id,
        "cover_image": event.cover_image,
        "created_at": event.created_at,
        "updated_at": event.updated_at,
        "creator_name": creator.full_name if creator else "Unknown",
        "creator_avatar": creator.avatar_url if creator else None,
        "participations": participations,
        "present_count": present_count,
        "absent_count": absent_count,
        "maybe_count": maybe_count,
        "pending_count": pending_count
    }

def update_user_attendance_rate(user: User, db: Session):
    """Update user attendance rate based on past events."""
    past_participations = db.query(EventParticipation).join(Event).filter(
        EventParticipation.user_id == user.id,
        Event.date < datetime.utcnow(),
        EventParticipation.status.in_([ParticipationStatus.PRESENT, ParticipationStatus.ABSENT])
    ).all()
    
    if past_participations:
        present_count = sum(1 for p in past_participations if p.status == ParticipationStatus.PRESENT)
        user.attendance_rate = (present_count / len(past_participations)) * 100
        db.commit()
