from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from typing import Optional, Dict, Any
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.core.auth import get_password_hash, verify_password, create_access_token, check_trip_auth
from app.schemas.trip import TripCreate, TripResponse, TripWithParticipants
from app.schemas.auth import TripAuthRequest, TripAuthResponse
from app.models.trip import Trip
from app.models.participant import Participant
import random
import string

router = APIRouter()

def generate_share_code():
    """Generate a unique 6-character share code"""
    while True:
        code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
        # Check if code already exists (we'll do this in the route for simplicity)
        return code

@router.post("")
@router.post("/")
async def create_trip(trip: TripCreate, db: Session = Depends(get_db)):
    """Create a new trip"""
    # Generate unique share code
    share_code = generate_share_code()
    while db.query(Trip).filter(Trip.share_code == share_code).first():
        share_code = generate_share_code()

    # Hash password if provided
    password_hash = None
    if trip.password and trip.password.strip():
        password_hash = get_password_hash(trip.password.strip())

    # Create trip
    db_trip = Trip(
        name=trip.name,
        description=trip.description,
        creator_name=trip.creator_name,
        currency_code=trip.currency_code,
        share_code=share_code,
        password_hash=password_hash
    )
    db.add(db_trip)
    db.commit()
    db.refresh(db_trip)

    # Add creator as first participant
    creator = Participant(
        trip_id=db_trip.id,
        name=trip.creator_name,
        is_creator=True,
        is_active=True
    )
    db.add(creator)
    db.commit()

    # If trip has a password, create and return an access token for the creator
    if password_hash:
        # Automatically authenticate the creator
        access_token = create_access_token(data={"trip_id": db_trip.id})
        # Return trip data with access token (as dict to include extra field)
        trip_response = TripResponse.from_orm(db_trip)
        # Use model_dump with mode='json' to properly serialize datetimes
        response_data = trip_response.model_dump(mode='json')
        response_data["access_token"] = access_token
        response_data["requires_auth"] = True
        # Use JSONResponse to return dict with extra fields
        from fastapi.responses import JSONResponse
        return JSONResponse(content=response_data)
    
    return TripResponse.from_orm(db_trip)

@router.get("/{trip_id}", response_model=TripWithParticipants)
async def get_trip(
    trip_id: int,
    db: Session = Depends(get_db),
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(HTTPBearer(auto_error=False))
):
    """Get trip details with participants (requires authentication if trip has password)"""
    trip = check_trip_auth(trip_id, credentials, db)

    # Get participants
    participants = db.query(Participant).filter(
        Participant.trip_id == trip_id,
        Participant.is_active == True
    ).all()

    trip_with_participants = TripWithParticipants(
        id=trip.id,
        name=trip.name,
        description=trip.description,
        creator_name=trip.creator_name,
        currency_code=trip.currency_code,
        share_code=trip.share_code,
        is_active=trip.is_active,
        created_at=trip.created_at,
        updated_at=trip.updated_at,
        participants=[
            {"id": p.id, "name": p.name, "is_creator": p.is_creator}
            for p in participants
        ]
    )

    return trip_with_participants

@router.get("/share/{share_code}", response_model=TripWithParticipants)
async def get_trip_by_share_code(share_code: str, db: Session = Depends(get_db)):
    """Get trip details by share code (does not require auth, but returns if password protected)"""
    trip = db.query(Trip).filter(Trip.share_code == share_code, Trip.is_active == "active").first()
    if not trip:
        raise HTTPException(status_code=404, detail="Trip not found")
    
    # If trip has password, don't return full details - just indicate it's password protected
    # The frontend will need to authenticate separately
    if trip.password_hash is not None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="This trip is password protected. Please authenticate.",
            headers={"WWW-Authenticate": "Bearer"},
        )

    # Get participants
    participants = db.query(Participant).filter(
        Participant.trip_id == trip.id,
        Participant.is_active == True
    ).all()

    trip_with_participants = TripWithParticipants(
        id=trip.id,
        name=trip.name,
        description=trip.description,
        creator_name=trip.creator_name,
        currency_code=trip.currency_code,
        share_code=trip.share_code,
        is_active=trip.is_active,
        created_at=trip.created_at,
        updated_at=trip.updated_at,
        participants=[
            {"id": p.id, "name": p.name, "is_creator": p.is_creator}
            for p in participants
        ]
    )

    return trip_with_participants