"""
Admin Router - Protected endpoints for admin users only.
User management, content CRUD, platform stats.
"""
from typing import List, Optional
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlmodel import Session, select, func
from pydantic import BaseModel
from database import get_session
from models import User, Profile, Show, Song, Venue, Tour, Rating, Comment, Review, Attendance, Artist
from dependencies import RoleChecker
from auth import get_password_hash

router = APIRouter(prefix="/admin", tags=["admin"])

# Only admins can access these endpoints
allow_admin = RoleChecker(["admin"])


# ============ SCHEMAS ============

class UserUpdate(BaseModel):
    role: Optional[str] = None
    is_active: Optional[bool] = None
    email_verified: Optional[bool] = None

class UserListItem(BaseModel):
    id: int
    email: str
    role: str
    is_active: bool
    email_verified: bool
    created_at: Optional[datetime] = None
    
    class Config:
        from_attributes = True

class ShowCreate(BaseModel):
    date: datetime
    vertical_id: int
    venue_id: Optional[int] = None
    tour_id: Optional[int] = None
    notes: Optional[str] = None
    bandcamp_link: Optional[str] = None
    nugs_link: Optional[str] = None
    youtube_link: Optional[str] = None

class ShowUpdate(BaseModel):
    date: Optional[datetime] = None
    venue_id: Optional[int] = None
    tour_id: Optional[int] = None
    notes: Optional[str] = None
    bandcamp_link: Optional[str] = None
    nugs_link: Optional[str] = None
    youtube_link: Optional[str] = None

class SongCreate(BaseModel):
    title: str
    vertical_id: int
    original_artist: Optional[str] = None
    notes: Optional[str] = None
    youtube_link: Optional[str] = None

class SongUpdate(BaseModel):
    title: Optional[str] = None
    original_artist: Optional[str] = None
    notes: Optional[str] = None
    youtube_link: Optional[str] = None

class VenueCreate(BaseModel):
    name: str
    city: str
    state: Optional[str] = None
    country: str = "USA"
    capacity: Optional[int] = None

class VenueUpdate(BaseModel):
    name: Optional[str] = None
    city: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    capacity: Optional[int] = None

class TourCreate(BaseModel):
    name: str
    vertical_id: int
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None


class TourUpdate(BaseModel):
    name: Optional[str] = None
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None

class ArtistUpdate(BaseModel):
    bio: Optional[str] = None
    image_url: Optional[str] = None
    notes: Optional[str] = None


class PlatformStats(BaseModel):
    total_users: int
    verified_users: int
    total_shows: int
    total_songs: int
    total_venues: int
    total_ratings: int
    total_reviews: int
    total_comments: int


# ============ STATS ============

@router.get("/stats", response_model=PlatformStats)
def get_platform_stats(
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Get platform-wide statistics"""
    return PlatformStats(
        total_users=session.exec(select(func.count(User.id))).one(),
        verified_users=session.exec(select(func.count(User.id)).where(User.email_verified == True)).one(),
        total_shows=session.exec(select(func.count(Show.id))).one(),
        total_songs=session.exec(select(func.count(Song.id))).one(),
        total_venues=session.exec(select(func.count(Venue.id))).one(),
        total_ratings=session.exec(select(func.count(Rating.id))).one(),
        total_reviews=session.exec(select(func.count(Review.id))).one(),
        total_comments=session.exec(select(func.count(Comment.id))).one(),
    )


# ============ USERS ============

@router.get("/users")
def list_users(
    skip: int = 0,
    limit: int = 50,
    search: Optional[str] = None,
    role: Optional[str] = None,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """List all users with optional filtering"""
    query = select(User)
    
    if search:
        query = query.where(User.email.contains(search))
    if role:
        query = query.where(User.role == role)
    
    query = query.offset(skip).limit(limit)
    users = session.exec(query).all()
    
    # Get profiles for usernames
    result = []
    for user in users:
        profile = session.exec(select(Profile).where(Profile.user_id == user.id)).first()
        result.append({
            "id": user.id,
            "email": user.email,
            "username": profile.username if profile else None,
            "role": user.role,
            "is_active": user.is_active,
            "email_verified": user.email_verified,
        })
    
    return result


@router.get("/users/{user_id}")
def get_user(
    user_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Get user details with activity stats"""
    user = session.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    profile = session.exec(select(Profile).where(Profile.user_id == user.id)).first()
    
    return {
        "id": user.id,
        "email": user.email,
        "username": profile.username if profile else None,
        "role": user.role,
        "is_active": user.is_active,
        "email_verified": user.email_verified,
        "bio": user.bio,
        "stats": {
            "ratings": session.exec(select(func.count(Rating.id)).where(Rating.user_id == user.id)).one(),
            "reviews": session.exec(select(func.count(Review.id)).where(Review.user_id == user.id)).one(),
            "comments": session.exec(select(func.count(Comment.id)).where(Comment.user_id == user.id)).one(),
            "attendances": session.exec(select(func.count(Attendance.id)).where(Attendance.user_id == user.id)).one(),
        }
    }


@router.patch("/users/{user_id}")
def update_user(
    user_id: int,
    update: UserUpdate,
    session: Session = Depends(get_session),
    admin: User = Depends(allow_admin)
):
    """Update user role, status, or verification"""
    user = session.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    # Prevent admin from demoting themselves
    if user.id == admin.id and update.role and update.role != "admin":
        raise HTTPException(status_code=400, detail="Cannot demote yourself")
    
    if update.role is not None:
        user.role = update.role
    if update.is_active is not None:
        user.is_active = update.is_active
    if update.email_verified is not None:
        user.email_verified = update.email_verified
    
    session.add(user)
    session.commit()
    session.refresh(user)
    
    return {"message": "User updated", "user_id": user.id}


# ============ SHOWS ============

@router.post("/shows")
def create_show(
    show_data: ShowCreate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Create a new show"""
    show = Show(**show_data.model_dump())
    session.add(show)
    session.commit()
    session.refresh(show)
    return show


@router.patch("/shows/{show_id}")
def update_show(
    show_id: int,
    update: ShowUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update show details"""
    show = session.get(Show, show_id)
    if not show:
        raise HTTPException(status_code=404, detail="Show not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(show, key, value)
    
    session.add(show)
    session.commit()
    session.refresh(show)
    return show


@router.delete("/shows/{show_id}")
def delete_show(
    show_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Delete a show"""
    show = session.get(Show, show_id)
    if not show:
        raise HTTPException(status_code=404, detail="Show not found")
    
    session.delete(show)
    session.commit()
    return {"message": "Show deleted", "show_id": show_id}


# ============ SONGS ============

@router.post("/songs")
def create_song(
    song_data: SongCreate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Create a new song"""
    song = Song(**song_data.model_dump())
    session.add(song)
    session.commit()
    session.refresh(song)
    return song


@router.patch("/songs/{song_id}")
def update_song(
    song_id: int,
    update: SongUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update song details"""
    song = session.get(Song, song_id)
    if not song:
        raise HTTPException(status_code=404, detail="Song not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(song, key, value)
    
    session.add(song)
    session.commit()
    session.refresh(song)
    return song


@router.delete("/songs/{song_id}")
def delete_song(
    song_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Delete a song"""
    song = session.get(Song, song_id)
    if not song:
        raise HTTPException(status_code=404, detail="Song not found")
    
    session.delete(song)
    session.commit()
    return {"message": "Song deleted", "song_id": song_id}


# ============ VENUES ============

@router.post("/venues")
def create_venue(
    venue_data: VenueCreate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Create a new venue"""
    venue = Venue(**venue_data.model_dump())
    session.add(venue)
    session.commit()
    session.refresh(venue)
    return venue


@router.patch("/venues/{venue_id}")
def update_venue(
    venue_id: int,
    update: VenueUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update venue details"""
    venue = session.get(Venue, venue_id)
    if not venue:
        raise HTTPException(status_code=404, detail="Venue not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(venue, key, value)
    
    session.add(venue)
    session.commit()
    session.refresh(venue)
    return venue


@router.delete("/venues/{venue_id}")
def delete_venue(
    venue_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Delete a venue"""
    venue = session.get(Venue, venue_id)
    if not venue:
        raise HTTPException(status_code=404, detail="Venue not found")
    
    session.delete(venue)
    session.commit()
    return {"message": "Venue deleted", "venue_id": venue_id}


# ============ TOURS ============

@router.post("/tours")
def create_tour(
    tour_data: TourCreate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Create a new tour"""
    tour = Tour(**tour_data.model_dump())
    session.add(tour)
    session.commit()
    session.refresh(tour)
    return tour


@router.patch("/tours/{tour_id}")
def update_tour(
    tour_id: int,
    update: TourUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update tour details"""
    tour = session.get(Tour, tour_id)
    if not tour:
        raise HTTPException(status_code=404, detail="Tour not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(tour, key, value)
    
    session.add(tour)
    session.commit()
    session.refresh(tour)
    return tour


@router.delete("/tours/{tour_id}")
def delete_tour(
    tour_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Delete a tour"""
    tour = session.get(Tour, tour_id)
    if not tour:
        raise HTTPException(status_code=404, detail="Tour not found")
    
    session.delete(tour)
    session.commit()
    return {"message": "Tour deleted", "tour_id": tour_id}


# ============ ARTISTS ============

@router.get("/artists")
def list_artists(
    skip: int = 0,
    limit: int = 50,
    search: Optional[str] = None,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """List all artists with optional search"""
    query = select(Artist)
    
    if search:
        query = query.where(Artist.name.icontains(search))
    
    query = query.order_by(Artist.name).offset(skip).limit(limit)
    artists = session.exec(query).all()
    
    return [
        {
            "id": a.id,
            "name": a.name,
            "slug": a.slug,
            "bio": a.bio,
            "image_url": a.image_url,
            "notes": a.notes,
        }
        for a in artists
    ]


@router.patch("/artists/{artist_id}")
def update_artist(
    artist_id: int,
    update: ArtistUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update artist details (bio, image, notes)"""
    artist = session.get(Artist, artist_id)
    if not artist:
        raise HTTPException(status_code=404, detail="Artist not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(artist, key, value)
    
    session.add(artist)
    session.commit()
    session.refresh(artist)
    return artist


# ============ PERFORMANCES ============

from models import Performance

class PerformanceUpdate(BaseModel):
    notes: Optional[str] = None
    youtube_link: Optional[str] = None
    bandcamp_link: Optional[str] = None
    nugs_link: Optional[str] = None
    track_url: Optional[str] = None


@router.patch("/performances/{performance_id}")
def update_performance(
    performance_id: int,
    update: PerformanceUpdate,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Update performance links and notes"""
    performance = session.get(Performance, performance_id)
    if not performance:
        raise HTTPException(status_code=404, detail="Performance not found")
    
    for key, value in update.model_dump(exclude_unset=True).items():
        setattr(performance, key, value)
    
    session.add(performance)
    session.commit()
    session.refresh(performance)
    return performance


@router.get("/performances/{performance_id}")
def get_performance(
    performance_id: int,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Get performance details for admin"""
    performance = session.get(Performance, performance_id)
    if not performance:
        raise HTTPException(status_code=404, detail="Performance not found")
    
    return {
        "id": performance.id,
        "slug": performance.slug,
        "show_id": performance.show_id,
        "song_id": performance.song_id,
        "position": performance.position,
        "set_name": performance.set_name,
        "notes": performance.notes,
        "youtube_link": performance.youtube_link,
        "bandcamp_link": performance.bandcamp_link,
        "nugs_link": performance.nugs_link,
        "track_url": performance.track_url,
    }


class BulkLinksImport(BaseModel):
    links: List[dict]  # {"show_id": 1, "platform": "nugs", "url": "..."} or {"performance_id": 1, ...}


@router.post("/import/external-links")
def bulk_import_links(
    data: BulkLinksImport,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Bulk import external links for shows and performances"""
    updated_shows = 0
    updated_performances = 0
    errors = []
    
    for item in data.links:
        platform = item.get("platform", "").lower()
        url = item.get("url")
        
        if not platform or not url:
            errors.append({"item": item, "error": "Missing platform or url"})
            continue
        
        field_name = f"{platform}_link"
        
        if "show_id" in item:
            show = session.get(Show, item["show_id"])
            if show and hasattr(show, field_name):
                setattr(show, field_name, url)
                session.add(show)
                updated_shows += 1
            else:
                errors.append({"item": item, "error": "Show not found or invalid platform"})
        
        elif "performance_id" in item:
            perf = session.get(Performance, item["performance_id"])
            if perf and hasattr(perf, field_name):
                setattr(perf, field_name, url)
                session.add(perf)
                updated_performances += 1
            else:
                errors.append({"item": item, "error": "Performance not found or invalid platform"})
    
    session.commit()
    
    return {
        "updated_shows": updated_shows,
        "updated_performances": updated_performances,
        "errors": errors
    }


# ============ EMAIL & NOTIFICATIONS ============

@router.post("/send-weekly-digest")
def trigger_weekly_digest(
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Manually trigger weekly digest emails (runs automatically every Sunday 9am UTC)"""
    from services.weekly_digest import send_weekly_digests
    
    try:
        send_weekly_digests()
        return {"message": "Weekly digest emails sent successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to send digest: {str(e)}")


@router.post("/test-email")
def test_email(
    to_email: str,
    session: Session = Depends(get_session),
    _: User = Depends(allow_admin)
):
    """Send a test email to verify email configuration"""
    from services.email_service import email_service
    
    subject = "Elmeg Test Email"
    html_content = """
    <html>
        <body style="font-family: sans-serif; padding: 20px;">
            <h2>Test Email</h2>
            <p>This is a test email from Elmeg to verify email configuration.</p>
            <p>If you received this, SMTP is working correctly!</p>
        </body>
    </html>
    """
    text_content = "This is a test email from Elmeg. If you received this, SMTP is working correctly!"
    
    success = email_service.send_email(to_email, subject, html_content, text_content)
    
    if success:
        return {"message": f"Test email sent to {to_email}"}
    else:
        raise HTTPException(status_code=500, detail="Failed to send test email")

