from fastapi import APIRouter, Depends, HTTPException, status, Request
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.responses import RedirectResponse
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from authlib.integrations.starlette_client import OAuth

from app.db.session import get_db
from app.services.auth_service import AuthService
from app.services.social_auth_service import SocialAuthService
from app.core.security import create_tokens, DEFAULT_RANK_MAP
from app.core.config import settings
from app.schemas.auth import (
    UserLiteRegister, Token, PasswordResetRequest, 
    UserKYCComplete, PasswordResetConfirm
)
from app.api.deps import get_current_user
from app.models.identity import User

router = APIRouter()

# --- GOOGLE OAUTH KONFIGURÁCIÓ ---
oauth = OAuth()
oauth.register(
    name='google',
    client_id=settings.GOOGLE_CLIENT_ID,
    client_secret=settings.GOOGLE_CLIENT_SECRET,
    server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
    client_kwargs={'scope': 'openid email profile'}
)

# --- SOCIAL AUTH ENDPOINTS ---

@router.get("/login/google")
async def login_google(request: Request):
    """
    Step 1: Átirányítás a Google bejelentkező oldalára.
    """
    redirect_uri = settings.GOOGLE_CALLBACK_URL
    return await oauth.google.authorize_redirect(request, redirect_uri)

@router.get("/callback/google")
async def auth_google(request: Request, db: AsyncSession = Depends(get_db)):
    """
    Step 2: Google visszahívás lekezelése + Dupla Token generálás.
    """
    try:
        token = await oauth.google.authorize_access_token(request)
        user_info = token.get('userinfo')
    except Exception:
        raise HTTPException(status_code=400, detail="Google hitelesítési hiba.")

    if not user_info:
        raise HTTPException(status_code=400, detail="Nincs adat a Google-től.")

    # Step 1: Technikai user létrehozása/keresése (inaktív, nincs mappa)
    user = await SocialAuthService.get_or_create_social_user(
        db, provider="google", social_id=user_info['sub'], email=user_info['email'],
        first_name=user_info.get('given_name'), last_name=user_info.get('family_name')
    )

    # Dinamikus token generálás
    ranks = await settings.get_db_setting(db, "rbac_rank_matrix", default=DEFAULT_RANK_MAP)
    role_name = user.role.value if hasattr(user.role, 'value') else str(user.role)
    user_rank = ranks.get(role_name, 10)

    token_data = {
        "sub": str(user.id),
        "role": role_name,
        "rank": user_rank,
        "scope_level": user.scope_level or "individual",
        "scope_id": user.scope_id or str(user.id),
        "region": user.region_code
    }
    
    access, refresh = create_tokens(data=token_data)
    
    # Visszatérés a frontendre mindkét tokennel
    response_url = f"{settings.FRONTEND_BASE_URL}/auth/callback?access={access}&refresh={refresh}"
    return RedirectResponse(url=response_url)


# --- STANDARD AUTH ENDPOINTS ---

@router.post("/register-lite", response_model=Token, status_code=status.HTTP_201_CREATED)
async def register_lite(user_in: UserLiteRegister, db: AsyncSession = Depends(get_db)):
    """Step 1: Manuális regisztráció (inaktív, nincs mappa)."""
    stmt = select(User).where(User.email == user_in.email)
    if (await db.execute(stmt)).scalar_one_or_none():
        raise HTTPException(status_code=400, detail="Email már regisztrálva.")
    
    user = await AuthService.register_lite(db, user_in)
    
    ranks = await settings.get_db_setting(db, "rbac_rank_matrix", default=DEFAULT_RANK_MAP)
    role_name = user.role.value if hasattr(user.role, 'value') else str(user.role)
    
    token_data = {
        "sub": str(user.id),
        "role": role_name,
        "rank": ranks.get(role_name, 10),
        "scope_level": "individual",
        "scope_id": str(user.id),
        "region": user.region_code
    }
    
    access, refresh = create_tokens(data=token_data)
    return {
        "access_token": access, 
        "refresh_token": refresh, 
        "token_type": "bearer", 
        "is_active": user.is_active
    }

@router.post("/login", response_model=Token)
async def login(db: AsyncSession = Depends(get_db), form_data: OAuth2PasswordRequestForm = Depends()):
    """Hagyományos belépés + Dupla Token."""
    user = await AuthService.authenticate(db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(status_code=401, detail="Hibás adatok.")
    
    ranks = await settings.get_db_setting(db, "rbac_rank_matrix", default=DEFAULT_RANK_MAP)
    role_name = user.role.value if hasattr(user.role, 'value') else str(user.role)
    user_rank = ranks.get(role_name, 10)

    token_data = {
        "sub": str(user.id),
        "role": role_name,
        "rank": user_rank,
        "scope_level": user.scope_level or "individual",
        "scope_id": user.scope_id or str(user.id),
        "region": user.region_code
    }
    
    access, refresh = create_tokens(data=token_data)
    return {
        "access_token": access, 
        "refresh_token": refresh, 
        "token_type": "bearer", 
        "is_active": user.is_active
    }

@router.get("/verify-email")
async def verify_email(token: str, db: AsyncSession = Depends(get_db)):
    if not await AuthService.verify_email(db, token):
        raise HTTPException(status_code=400, detail="Érvénytelen token.")
    return {"message": "Email megerősítve!"}

@router.post("/complete-kyc")
async def complete_kyc(
    kyc_in: UserKYCComplete, 
    db: AsyncSession = Depends(get_db), 
    current_user: User = Depends(get_current_user)
):
    """
    Step 2: KYC Aktiválás.
    Itt használjuk a get_current_user-t (nem active), mert a user még inaktív.
    """
    user = await AuthService.complete_kyc(db, current_user.id, kyc_in)
    if not user:
        raise HTTPException(status_code=404, detail="User nem található.")
    return {"status": "success", "message": "Fiók aktiválva."}

@router.post("/forgot-password")
async def forgot_password(req: PasswordResetRequest, db: AsyncSession = Depends(get_db)):
    result = await AuthService.initiate_password_reset(db, req.email)
    if result == "cooldown":
        raise HTTPException(status_code=429, detail="Túl sok kérés.")
    return {"message": "Visszaállító link kiküldve."}

@router.post("/reset-password")
async def reset_password(req: PasswordResetConfirm, db: AsyncSession = Depends(get_db)):
    if req.password != req.password_confirm:
        raise HTTPException(status_code=400, detail="Nem egyeznek a jelszavak.")
    if not await AuthService.reset_password(db, req.email, req.token, req.password):
        raise HTTPException(status_code=400, detail="Sikertelen frissítés.")
    return {"message": "Jelszó frissítve!"}