from fastapi import APIRouter, Depends, HTTPException, Request, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from app.core.deps import DB, CurrentUser, get_current_user
from app.core.security import decode_token, create_access_token, create_refresh_token
from app.core.database import get_db
from app.models.user import User
from app.schemas.auth import (
    LoginRequest, TokenResponse, RefreshTokenRequest,
    RegisterStudentRequest, RegisterParentRequest, RegisterSchoolRequest,
    RegisterTeacherRequest, RegisterOrganizationRequest,
    ChangePasswordRequest, ForgotPasswordRequest
)
from app.schemas.user import UserOut
from app.services.auth_service import (
    authenticate_user, build_token_response,
    register_student, register_parent, register_teacher, register_school
)
from app.core.security import verify_password, hash_password

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


@router.post("/login", response_model=TokenResponse, summary="Login to StemGenius")
async def login(data: LoginRequest, request: Request, db: DB):
    """
    Authenticate with email/phone/username/stem_id + password.
    Returns JWT access token and refresh token.
    """
    user = await authenticate_user(db, data.identifier, data.password, request)
    return build_token_response(user)


@router.post("/register/student", response_model=TokenResponse, status_code=201,
             summary="Register as a Student")
async def register_as_student(data: RegisterStudentRequest, db: DB):
    """
    Create a new student account. Automatically receives:
    - A portable digital STEM ID
    - Free access (freemium subscription)
    """
    user = await register_student(db, data)
    return build_token_response(user)


@router.post("/register/parent", response_model=TokenResponse, status_code=201,
             summary="Register as a Parent")
async def register_as_parent(data: RegisterParentRequest, db: DB):
    """Create a parent account to monitor children and make payments."""
    user = await register_parent(db, data)
    return build_token_response(user)


@router.post("/register/teacher", response_model=TokenResponse, status_code=201,
             summary="Register as a Teacher")
async def register_as_teacher(data: RegisterTeacherRequest, db: DB):
    """
    Create a teacher account with a portable teacher code.
    Teachers can submit questions and track student progress.
    """
    user = await register_teacher(db, data)
    return build_token_response(user)


@router.post("/register/school", response_model=TokenResponse, status_code=201,
             summary="Register a School")
async def register_as_school(data: RegisterSchoolRequest, db: DB):
    """
    Register a school account. School accounts require admin verification
    before gaining full access.
    """
    user = await register_school(db, data)
    return build_token_response(user)


@router.post("/register/organization", response_model=TokenResponse, status_code=201,
             summary="Register an Organization")
async def register_as_organization(data: RegisterOrganizationRequest, db: DB):
    """Register an organization that can affiliate with schools."""
    from app.core.security import hash_password, generate_stem_id, generate_access_code
    from app.models.user import User
    from app.models.school import Organization
    from sqlalchemy import select

    existing = await db.execute(select(User).where(User.email == data.email))
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=400, detail="Email already registered")

    stem_id = generate_stem_id("ORG")
    org_code = generate_stem_id("OG")[:10]

    user = User(
        stem_id=stem_id,
        email=data.email,
        phone=data.phone,
        password_hash=hash_password(data.password),
        first_name=data.org_name,
        last_name="Organization",
        role="organization",
    )
    db.add(user)
    await db.flush()

    org = Organization(
        user_id=user.id,
        org_name=data.org_name,
        org_code=org_code,
        org_type=data.org_type,
        address=data.address,
        city=data.city,
        country=data.country,
        contact_email=data.email,
        registration_number=data.registration_number,
    )
    db.add(org)
    await db.commit()
    await db.refresh(user)

    from app.services.auth_service import build_token_response
    return build_token_response(user)


@router.post("/refresh", response_model=TokenResponse, summary="Refresh Access Token")
async def refresh_token(data: RefreshTokenRequest, db: DB):
    """Exchange a valid refresh token for a new access token."""
    payload = decode_token(data.refresh_token)
    if not payload or payload.get("type") != "refresh":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid or expired refresh token",
        )
    user_id = int(payload.get("sub"))
    result = await db.execute(select(User).where(User.id == user_id, User.is_active == True))
    user = result.scalar_one_or_none()
    if not user:
        raise HTTPException(status_code=401, detail="User not found")

    from app.services.auth_service import build_token_response
    return build_token_response(user)


@router.get("/me", response_model=UserOut, summary="Get Current User Profile")
async def get_me(current_user: CurrentUser):
    """Return the currently authenticated user's profile."""
    return current_user


@router.post("/change-password", summary="Change Password")
async def change_password(data: ChangePasswordRequest, current_user: CurrentUser, db: DB):
    """Change the authenticated user's password."""
    if not verify_password(data.current_password, current_user.password_hash):
        raise HTTPException(status_code=400, detail="Current password is incorrect")
    current_user.password_hash = hash_password(data.new_password)
    await db.commit()
    return {"message": "Password changed successfully"}


@router.post("/logout", summary="Logout")
async def logout(current_user: CurrentUser):
    """Logout the current user (client should discard tokens)."""
    return {"message": "Logged out successfully"}


@router.get("/subscription-status", summary="Check Subscription Status")
async def check_subscription(current_user: CurrentUser, db: DB):
    """Check the current user's subscription and access level."""
    from app.services.subscription_service import check_premium_access
    return await check_premium_access(db, current_user.id)
