#!/usr/bin/env python3
"""
Teams management for users and admins.
"""
from fastapi import APIRouter, Depends, Request, Form, HTTPException, status, BackgroundTasks
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlalchemy.orm import Session
from sqlalchemy import func, desc, inspect, or_, and_
from datetime import datetime, timedelta
import random  # For demo data
import secrets
from starlette.status import HTTP_303_SEE_OTHER
from starlette.middleware.sessions import SessionMiddleware

from ..db import SessionLocal, get_db
from ..models import Team, TeamMembership, User, QRCode, TeamAchievement, TeamJoinRequest
from ..schemas import TeamCreate
from ..templates_config import templates
from ..utils.auth import get_current_user, is_team_captain
from ..utils.mail import send_team_join_request_notification, send_join_request_response
from ..auth.permissions import require_auth, require_team_captain

router = APIRouter()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@router.get("/", response_class=HTMLResponse)
def list_teams(request: Request, db: Session = Depends(get_db)):
    teams = db.query(Team).all()
    
    # Get the user's teams to highlight teams they're already in
    user_team_ids = []
    
    # Get user from session for navbar
    user = None
    user_id = request.session.get("user_id")
    if user_id:
        user = db.query(User).get(user_id)
        # Get teams that user is a member of
        memberships = db.query(TeamMembership).filter(TeamMembership.user_id == user_id).all()
        user_team_ids = [membership.team_id for membership in memberships]
    
    # Get error message if present
    error = request.query_params.get("error")
    
    return templates.TemplateResponse(
        "teams.html", 
        {
            "request": request, 
            "teams": teams,
            "user_team_ids": user_team_ids,
            "user": user,
            "error": error,
            "brand_colors": {
                "irish_green": "#006837",
                "golden_ale": "#FFB400",
                "cream_white": "#F5F0E1",
                "black_stout": "#1A1A1A",
                "guinness_red": "#B22222"
            }
        }
    )

@router.post("/create", response_class=HTMLResponse)
async def create_team_post(
    request: Request,
    name: str = Form(...),
    description: str = Form(""),
    logo_url: str = Form(""),
    is_open: bool = Form(False),  # Added is_open field
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """Handle team creation form submission"""
    if not current_user:
        return RedirectResponse("/auth/login", status_code=HTTP_303_SEE_OTHER)
    
    # Check if team name already exists
    existing_team = db.query(Team).filter(Team.name == name).first()
    if existing_team:
        return RedirectResponse("/teams/?error=Team+name+already+exists", status_code=HTTP_303_SEE_OTHER)
    
    # Create team
    team = Team(
        name=name,
        description=description,
        logo_url=logo_url,
        is_open=is_open,  # Save is_open value
        owner_id=current_user.id  # Set the owner_id field
    )
    db.add(team)
    db.commit()
    db.refresh(team)
    
    # Make the user an admin and captain of the team in TeamMembership
    team_membership = TeamMembership(
        user_id=current_user.id,
        team_id=team.id,
        is_admin=True,
        is_captain=True  # User becomes both admin and captain of the team
    )
    db.add(team_membership)
    db.commit()

    return RedirectResponse("/teams/", status_code=HTTP_303_SEE_OTHER)

@router.post("/teams/{team_id}/edit", response_class=HTMLResponse)
async def edit_team_post(
    request: Request,
    team_id: int,
    name: str = Form(...),
    description: str = Form(""),
    logo_url: str = Form(""),
    is_open: bool = Form(False),  # Added is_open field
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """Handle team edit form submission"""
    if not current_user:
        return RedirectResponse("/auth/login", status_code=HTTP_303_SEE_OTHER)
    
    team = db.query(Team).filter(Team.id == team_id).first()
    if not team:
        raise HTTPException(status_code=404, detail="Team not found")
    
    # Check if user is admin
    membership = db.query(TeamMembership).filter_by(
        team_id=team.id,
        is_admin=True
    ).first()
    
    if not membership:
        raise HTTPException(status_code=403, detail="You don't have permission to update this team")
    
    # Update team details
    team.name = name
    team.description = description
    team.logo_url = logo_url
    team.is_open = is_open  # Update is_open value
    db.commit()
    
    return RedirectResponse(f"/teams/{team_id}", status_code=HTTP_303_SEE_OTHER)

@router.get("/{team_id}/join", response_class=HTMLResponse)
async def join_team_page(
    request: Request,
    team_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """Page for joining a team"""
    if not current_user:
        return RedirectResponse(f"/auth/login?next=/teams/{team_id}/join", status_code=HTTP_303_SEE_OTHER)
    
    # Check if team exists
    team = db.query(Team).filter(Team.id == team_id, Team.is_active == True).first()
    if not team:
        return templates.TemplateResponse(
            "error.html",
            {"request": request, "error": "Team not found"}
        )
    
    # Check if user is already a member
    existing_membership = db.query(TeamMembership).filter(
        TeamMembership.team_id == team_id, 
        TeamMembership.user_id == current_user.id
    ).first()
    
    if existing_membership:
        return templates.TemplateResponse(
            "teams/join_team.html",
            {
                "request": request, 
                "team": team, 
                "error": "You are already a member of this team"
            }
        )
    
    # Check if there's a pending join request
    pending_request = db.query(TeamJoinRequest).filter(
        TeamJoinRequest.team_id == team_id,
        TeamJoinRequest.user_id == current_user.id,
        TeamJoinRequest.status == "pending"
    ).first()
    
    if pending_request:
        return templates.TemplateResponse(
            "teams/join_team.html",
            {
                "request": request, 
                "team": team, 
                "error": "You already have a pending join request for this team"
            }
        )
    
    return templates.TemplateResponse(
        "teams/join_team.html",
        {"request": request, "team": team, "is_open": team.is_open}
    )

@router.post("/{team_id}/join", response_class=HTMLResponse)
async def join_team_request(
    request: Request,
    team_id: int,
    background_tasks: BackgroundTasks,
    message: str = Form(""),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """Process join team request"""
    if not current_user:
        return RedirectResponse("/auth/login", status_code=HTTP_303_SEE_OTHER)
    
    # Check if team exists
    team = db.query(Team).filter(Team.id == team_id, Team.is_active == True).first()
    if not team:
        return templates.TemplateResponse(
            "error.html",
            {"request": request, "error": "Team not found"}
        )
    
    # Check if user is already a member
    existing_membership = db.query(TeamMembership).filter(
        TeamMembership.team_id == team_id, 
        TeamMembership.user_id == current_user.id
    ).first()
    
    if existing_membership:
        return RedirectResponse(f"/teams/{team_id}", status_code=HTTP_303_SEE_OTHER)
    
    # Open team - directly add the user
    if team.is_open:
        # Add user to team
        new_member = TeamMembership(
            team_id=team_id,
            user_id=current_user.id,
            is_captain=False,
            is_admin=False
        )
        
        db.add(new_member)
        db.commit()
        
        return RedirectResponse(
            f"/teams/{team_id}?message=You+have+joined+the+team+successfully", 
            status_code=HTTP_303_SEE_OTHER
        )
    
    # Closed team - create join request
    # Check for existing pending request
    existing_request = db.query(TeamJoinRequest).filter(
        TeamJoinRequest.team_id == team_id,
        TeamJoinRequest.user_id == current_user.id,
        TeamJoinRequest.status == "pending"
    ).first()
    
    if existing_request:
        return RedirectResponse(
            f"/teams/{team_id}?message=Your+join+request+is+pending+approval", 
            status_code=HTTP_303_SEE_OTHER
        )
    
    # Create request token
    request_token = secrets.token_urlsafe(32)
    
    # Create join request
    join_request = TeamJoinRequest(
        team_id=team_id,
        user_id=current_user.id,
        message=message,
        request_token=request_token
    )
    
    db.add(join_request)
    db.commit()
    
    # Get team captains to notify
    captains = db.query(User).join(TeamMembership).filter(
        TeamMembership.team_id == team_id,
        TeamMembership.is_captain == True
    ).all()
    
    if not captains:
        print("No captains found for the team. Unable to send notifications.")
    else:
        # Send email notifications to all captains
        for captain in captains:
            try:
                await send_team_join_request_notification(
                    captain_email=captain.email,
                    captain_name=captain.username,
                    requester_name=current_user.username,
                    team_name=team.name,
                    message=message,
                    approval_token=request_token,
                    background_tasks=background_tasks
                )
                # Log success
                print(f"Team join request notification sent to {captain.email}")
            except Exception as e:
                # Log the error but continue
                print(f"Failed to send notification to {captain.email}: {str(e)}")
    
    return RedirectResponse(
        f"/teams/{team_id}?message=Your+join+request+has+been+submitted+for+approval", 
        status_code=HTTP_303_SEE_OTHER
    )

@router.post("/join/{team_id}")
def direct_join_team(request: Request, team_id: int, db: Session = Depends(get_db)):
    """Handle direct team join requests"""
    # Check if user is logged in
    user_id = request.session.get("user_id")
    if not user_id:
        return RedirectResponse("/auth/login?next=/teams", status_code=303)
        
    # Get user
    user = db.query(User).get(user_id)
    if not user:
        return RedirectResponse("/auth/login", status_code=303)
    
    # Find the team
    team = db.query(Team).filter_by(id=team_id).first()
    if not team:
        return RedirectResponse("/teams/?error=Team+not+found", status_code=303)

    # Check if membership exists
    existing = db.query(TeamMembership)\
        .filter_by(user_id=user_id, team_id=team.id)\
        .first()
        
    if existing:
        return RedirectResponse("/teams/?error=You+are+already+a+member+of+this+team", status_code=303)
    
    # Check if team is closed (not open)
    if not team.is_open:
        # For closed teams, redirect to the join request page
        return RedirectResponse(f"/teams/{team_id}/join", status_code=303)

    # Create membership for open teams
    new_member = TeamMembership(
        user_id=user_id,
        team_id=team.id,
        is_admin=False,
        is_captain=False
    )
    db.add(new_member)
    db.commit()
    
    # Redirect to the team detail page
    return RedirectResponse(f"/teams/{team_id}", status_code=303)

@router.post("/{team_id}/leave")
def leave_team(request: Request, team_id: int, db: Session = Depends(get_db)):
    """Allow a user to leave a team"""
    # Check if user is logged in
    user_id = request.session.get("user_id")
    if not user_id:
        return RedirectResponse("/auth/login?next=/teams", status_code=303)
        
    # Get team
    team = db.query(Team).filter_by(id=team_id).first()
    if not team:
        raise HTTPException(status_code=404, detail="Team not found")
    
    # Can't leave if you're the owner
    if team.owner_id == user_id:
        return RedirectResponse(f"/teams/{team_id}?error=Team+owner+cannot+leave", status_code=303)
    
    # Find membership
    membership = db.query(TeamMembership)\
        .filter(TeamMembership.user_id == user_id, TeamMembership.team_id == team_id)\
        .first()
        
    if not membership:
        return RedirectResponse("/teams/?error=You+are+not+a+member+of+this+team", status_code=303)
    
    # Delete the team membership
    db.delete(membership)
    db.commit()
    
    return RedirectResponse("/teams/?message=Successfully+left+the+team", status_code=303)

@router.post("/{team_id}/update")
def update_team(
    request: Request,
    team_id: int, 
    team_name: str = Form(...), 
    is_public: bool = Form(False),
    db: Session = Depends(get_db)
):
    """Update team details."""
    team = db.query(Team).filter_by(id=team_id).first()
    
    if not team:
        raise HTTPException(status_code=404, detail="Team not found")
    
    # Check if user is admin
    membership = db.query(TeamMembership).filter_by(
        team_id=team.id,
        is_admin=True
    ).first()
    
    if not membership:
        raise HTTPException(status_code=403, detail="You don't have permission to update this team")
    
    # Update team details
    team.name = team_name
    team.is_public = is_public
    db.commit()
    
    return RedirectResponse(f"/teams/{team_id}", status_code=303)

@router.get("/{team_id}", response_class=HTMLResponse)
def team_detail(request: Request, team_id: int, db: Session = Depends(get_db)):
    """Show details for a specific team."""
    # Get team
    team = db.query(Team).filter_by(id=team_id).first()
    if not team:
        raise HTTPException(status_code=404, detail="Team not found")
    
    # Get user from session for navbar
    user = None
    user_id = request.session.get("user_id")
    is_team_member = False
    
    if user_id:
        user = db.query(User).get(user_id)
        
        # Check if user is a team member
        team_membership = db.query(TeamMembership)\
            .filter(TeamMembership.user_id == user_id, TeamMembership.team_id == team_id)\
            .first()
        
        is_team_member = team_membership is not None
    
    # Get team members with admin status
    memberships = db.query(TeamMembership).filter_by(team_id=team_id).all()
    team_members = []
    
    is_user_admin = False
    for membership in memberships:
        member = db.query(User).filter_by(id=membership.user_id).first()
        if member:
            # Check if current user is admin of this team
            if user and user.id == membership.user_id and membership.is_admin:
                is_user_admin = True
                
            # Use joined_at if available, otherwise use placeholder
            joined_date = getattr(membership, 'joined_at', None) or datetime.now() - timedelta(days=random.randint(30, 180))
            if isinstance(joined_date, datetime):
                month_name = joined_date.strftime("%b")
                year = joined_date.strftime("%Y")
            else:
                month_name = "Apr"
                year = "2023"
                
            team_members.append({
                "user": member,
                "is_admin": membership.is_admin,
                "joined": f"{month_name} {year}"
            })
    
    # Also check if user is the owner
    is_user_owner = user and team.owner_id == user.id
    if is_user_owner:
        is_user_admin = True  # Owner has admin privileges
    
    # Get total points
    total_points = db.query(func.sum(QRCode.points)).filter(
        QRCode.redeemed_at_team == team_id
    ).scalar() or 0
    
    # Calculate rank based on points - using a safer approach
    try:
        # First, get the aggregated points for all teams
        team_points = db.query(
            QRCode.redeemed_at_team, 
            func.sum(QRCode.points).label('total')
        ).filter(
            QRCode.redeemed_at_team != None
        ).group_by(QRCode.redeemed_at_team).all()
        
        # Sort them by points (descending)
        sorted_teams = sorted(team_points, key=lambda x: x.total or 0, reverse=True)
        
        # Find our team's position
        team_rank = 1
        for idx, team_data in enumerate(sorted_teams):
            if team_data.redeemed_at_team == team_id:
                team_rank = idx + 1
                break
            
    except Exception as e:
        print(f"Error calculating team rank: {e}")
        team_rank = 1  # Default to 1st place on error
    
    # Generate points data (with fallbacks for missing columns)
    points_this_month = 65  # Default value
    point_change = 15       # Default value
    point_change_positive = True
    
    # Check if redeemed_at column exists before using it
    try:
        now = datetime.now()
        first_day_of_month = datetime(now.year, now.month, 1)
        
        # Use raw SQL to check if column exists and get points
        has_redeemed_at = False
        inspector = inspect(db.bind)
        if 'redeemed_at' in [col['name'] for col in inspector.get_columns('qr_codes')]:
            has_redeemed_at = True
            
        if has_redeemed_at:
            points_this_month = db.query(func.sum(QRCode.points)).filter(
                QRCode.redeemed_at_team == team_id,
                QRCode.redeemed_at >= first_day_of_month
            ).scalar() or points_this_month
    except Exception as e:
        print(f"Error calculating monthly points: {e}")
    
    # Activities - simple mock data for now
    activities = [
        {
            "type": "points",
            "points": 15,
            "event": "Music Trivia Night",
            "date": "September 12, 2023"
        },
        {
            "type": "join",
            "user": "Robert Brown",
            "date": "July 28, 2023"
        },
        {
            "type": "achievement",
            "achievement": "1st place",
            "event": "History Night",
            "date": "July 15, 2023"
        },
        {
            "type": "points",
            "points": 20,
            "event": "Movie Trivia Night",
            "date": "July 1, 2023"
        }
    ]
    
    # Safely get team attributes
    is_public = getattr(team, 'is_public', False)
    is_open = getattr(team, 'is_open', False)  # Add this line to get is_open status
    created_at = getattr(team, 'created_at', None)
    
    # Calculate days since team was founded
    if created_at and isinstance(created_at, datetime):
        days_ago = (datetime.now() - created_at).days
        founded_date_str = created_at.strftime("%B %d, %Y")
    else:
        days_ago = 164  # Default fallback
        founded_date_str = "March 22, 2023"  # Default fallback
    
    # Performance metrics
    performance = {
        "last_quiz": "25 points (2nd place)",
        "average": "18.7 points",
        "best_streak": "3 wins in a row"
    }
    
    return templates.TemplateResponse(
        "team_detail.html",
        {
            "request": request,
            "team": team,
            "team_members": team_members,
            "team_rank": team_rank,
            "total_points": total_points,
            "points_this_month": points_this_month,
            "point_change": point_change,
            "point_change_positive": point_change_positive,
            "activities": activities,
            "performance": performance,
            "is_user_admin": is_user_admin,
            "is_user_owner": is_user_owner,
            "is_team_member": is_team_member,
            "days_ago": days_ago,
            "founded_date": founded_date_str,
            "user": user,  # Add user to the context
            "is_open": is_open  # Pass is_open to the template
        }
    )

@router.get("/{team_id}/manage", response_class=HTMLResponse)
@require_team_captain()
async def manage_team(request: Request, team_id: int, db: Session = Depends(get_db)):
    """
    Team management page for captains.
    This route is protected by the require_team_captain decorator which
    automatically checks if the user is a captain of the team.
    """
    # Get team
    team = db.query(Team).filter_by(id=team_id).first()
    if not team:
        raise HTTPException(status_code=404, detail="Team not found")
    
    # Get pending join requests
    join_requests = db.query(TeamJoinRequest).filter(
        TeamJoinRequest.team_id == team_id,
        TeamJoinRequest.status == "pending"
    ).all()
    
    # Get requesters' info
    pending_requests = []
    for req in join_requests:
        requester = db.query(User).filter(User.id == req.user_id).first()
        if requester:
            pending_requests.append({
                "request": req,
                "user": requester
            })
    
    # Get team members
    memberships = db.query(TeamMembership).filter_by(team_id=team_id).all()
    team_members = []
    
    for membership in memberships:
        member = db.query(User).filter_by(id=membership.user_id).first()
        if member:
            team_members.append({
                "user": member,
                "is_admin": membership.is_admin,
                "is_captain": membership.is_captain
            })
    
    # Get current user from session for template
    current_user = None
    if hasattr(request, "session") and request.session.get("user_id"):
        current_user = db.query(User).filter_by(id=request.session.get("user_id")).first()
    
    return templates.TemplateResponse(
        "teams/manage.html",
        {
            "request": request,
            "team": team,
            "pending_requests": pending_requests,
            "team_members": team_members,
            "user": current_user  # Use current user from session instead of request.user
        }
    )
