from fastapi import APIRouter, Request, Form, UploadFile, HTTPException, Depends
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
import os
import secrets
from sqlalchemy.orm import Session

from ..database import templates, BASE_DIR
from ..models.base import get_db
from ..models import auth_crud as crud
from .deps import rotate_session, pwd_context, current_user
from .email_utils import generate_password_reset_token, send_password_reset_email, verify_password_reset_token

router = APIRouter()

@router.get("/login", name="login", response_class=HTMLResponse)
async def login_get(request: Request):
    return templates.TemplateResponse("login.html", {"request": request, "error": None})

@router.post("/login", name="login_post", response_class=HTMLResponse)
async def login_post(request: Request, email: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)):
    email_norm = email.strip().lower()
    user_orm = crud.get_user_by_email(db, email_norm)
    user = crud.user_to_dict(user_orm) if user_orm else None
    if not user or not pwd_context.verify(password, user["password_hash"]):
        return templates.TemplateResponse("login.html", {"request": request, "error": "Credenciales inválidas"})
    rotate_session(request)
    request.session["user_id"] = int(user["id"])
    request.session["role"] = user["role"]
    if user["role"] == "admin" or email_norm == "admin@admin.es":
        return RedirectResponse(url=request.url_for("reservas_dashboard"), status_code=303)
    elif user["role"] == "docente":
        return RedirectResponse(url=request.url_for("docente"), status_code=303)
    else:
        return RedirectResponse(url=request.url_for("dashboard"), status_code=303)

@router.get("/recuperar-password", name="recuperar_password", response_class=HTMLResponse)
async def recuperar_password_get(request: Request):
    return templates.TemplateResponse("recuperar-password.html", {"request": request, "error": None, "success": None})

@router.post("/recuperar-password", name="recuperar_password_post", response_class=HTMLResponse)
async def recuperar_password_post(request: Request, email: str = Form(...), db: Session = Depends(get_db)):
    email_norm = email.strip().lower()
    user = crud.get_user_by_email(db, email_norm)
    
    if user:
        token = generate_password_reset_token(email_norm)
        # Construct base URL from request
        base_url = str(request.base_url).rstrip("/")
        # Run in background or wait? For simplicity, we wait.
        # Ideally this should be a background task: background_tasks.add_task(...)
        send_password_reset_email(email_norm, token, base_url)
        print(f"INFO: Recovery email sent to {email_norm}")

    return templates.TemplateResponse(
        "recuperar-password.html", 
        {
            "request": request, 
            "error": None, 
            "success": f"Si existe una cuenta con {email_norm}, recibirás un correo con las instrucciones."
        }
    )

@router.get("/reset-password", name="reset_password_get", response_class=HTMLResponse)
async def reset_password_get(request: Request, token: str):
    email = verify_password_reset_token(token)
    if not email:
        return templates.TemplateResponse("recuperar-password.html", {
            "request": request,
            "error": "El enlace de recuperación es inválido o ha caducado. Vuelve a solicitarlo.",
            "success": None
        })
    
    return templates.TemplateResponse("reset-password.html", {
        "request": request, 
        "token": token,
        "error": None,
        "success": None
    })

@router.post("/reset-password", name="reset_password_post", response_class=HTMLResponse)
async def reset_password_post(request: Request, token: str, password: str = Form(...), confirm_password: str = Form(...), db: Session = Depends(get_db)):
    email = verify_password_reset_token(token)
    if not email:
        return templates.TemplateResponse("recuperar-password.html", {
            "request": request,
            "error": "El enlace ha caducado. Por favor solicita uno nuevo.",
            "success": None
        })
    
    if password != confirm_password:
        return templates.TemplateResponse("reset-password.html", {
            "request": request,
            "token": token,
            "error": "Las contraseñas no coinciden."
        })
        
    if len(password) < 6:
        return templates.TemplateResponse("reset-password.html", {
            "request": request,
            "token": token,
            "error": "La contraseña debe tener al menos 6 caracteres."
        })

    user = crud.get_user_by_email(db, email)
    if not user:
        return templates.TemplateResponse("recuperar-password.html", {
            "request": request,
            "error": "Usuario no encontrado.",
            "success": None
        })

    # Update password
    # We use auth_crud which is aliased as crud
    try:
        updated = crud.set_user_password(db, user.id, password)
        if not updated:
            raise Exception("Falied to update")
    except AttributeError:
        # Fallback if set_user_password isn't found on the alias (it should be)
        raise HTTPException(status_code=500, detail="Error de configuración del servidor")

    return templates.TemplateResponse("reset-password.html", {
        "request": request,
        "token": token,
        "success": "Tu contraseña se ha actualizado correctamente.",
        "error": None
    })


@router.get("/logout", name="logout")
async def logout(request: Request):
    request.session.clear()
    return RedirectResponse(url="/", status_code=303)

@router.get("/register", name="register", response_class=HTMLResponse)
async def register_get(request: Request):
    me = current_user(request)
    ctx_user = me or {"name": "", "email": "", "phone": ""}
    return templates.TemplateResponse("register.html", {"request": request, "error": None, "user": ctx_user})

@router.post("/register", name="register_post", response_class=HTMLResponse)
async def register_post(request: Request, name: str = Form(...), email: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)):
    email_norm = email.strip().lower()
    existing_user = crud.get_user_by_email(db, email_norm)
    if existing_user:
        return templates.TemplateResponse(
            "register.html",
            {"request": request, "error": "Ese email ya existe", "user": {"name": name.strip(), "email": email_norm, "phone": ""}}
        )
    if len(password) < 6:
        return templates.TemplateResponse(
            "register.html",
            {"request": request, "error": "La contraseña debe tener 6+ caracteres", "user": {"name": name.strip(), "email": email_norm, "phone": ""}}
        )
    crud.create_user(db, name.strip(), email_norm, password, role="alumno")
    user_orm = crud.get_user_by_email(db, email_norm)
    user = crud.user_to_dict(user_orm)
    request.session["user_id"] = int(user["id"])
    request.session["role"] = user["role"]
    if user["role"] == "admin" or email_norm == "admin@admin.es":
        return RedirectResponse(url=request.url_for("reservas_dashboard"), status_code=303)
    else:
        return RedirectResponse(url=request.url_for("dashboard"), status_code=303)

@router.get("/academy-register", name="academy_register_get", response_class=HTMLResponse)
async def academy_register_get(request: Request):
    me = current_user(request)
    return templates.TemplateResponse(
        "academy-register.html",
        {"request": request, "user": me}
    )

@router.post("/academy-register", name="academy_register_post")
async def academy_register_post(request: Request, db: Session = Depends(get_db)):
    form = await request.form()
    email = (form.get("email") or "").strip().lower()
    name  = (form.get("name")  or "").strip()
    password = (form.get("password") or "")
    first_name = (form.get("firstName") or "").strip()
    last_name = (form.get("lastName") or "").strip()

    if not email:
        raise HTTPException(status_code=400, detail="El email es obligatorio.")
    if not first_name or len(first_name) < 2:
        raise HTTPException(status_code=400, detail="Indica tu nombre.")
    if not last_name or len(last_name) < 2:
        raise HTTPException(status_code=400, detail="Indica tus apellidos.")
    if not name or len(name) < 2:
        raise HTTPException(status_code=400, detail="Indica tu nombre (mínimo 2 caracteres).")
    if not password or len(password) < 6:
        raise HTTPException(status_code=400, detail="La contraseña debe tener al menos 6 caracteres.")
    
    # --- New Mandatory Validations ---
    if not form.get("dni"): raise HTTPException(status_code=400, detail="El DNI es obligatorio.")
    if not form.get("birthDate"): raise HTTPException(status_code=400, detail="La fecha de nacimiento es obligatoria.")
    if not form.get("gender"): raise HTTPException(status_code=400, detail="El sexo es obligatorio.")
    if not form.get("occupation"): raise HTTPException(status_code=400, detail="Indica si estudias o trabajas.")
    if not form.get("studyPlace"): raise HTTPException(status_code=400, detail="Indica dónde estudias.")
    if not form.get("category"): raise HTTPException(status_code=400, detail="Selecciona una categoría.")
    if not form.get("currentTeam"): raise HTTPException(status_code=400, detail="Indica tu equipo actual.")
    
    if not form.get("currentPosition"): raise HTTPException(status_code=400, detail="Indica tu posición actual.")
    if not form.get("dominantFoot"): raise HTTPException(status_code=400, detail="Indica tu pierna dominante.")
    if not form.get("preferredPosition"): raise HTTPException(status_code=400, detail="Indica tu posición preferida.")
    
    if not form.get("parentName"): raise HTTPException(status_code=400, detail="El nombre del tutor es obligatorio.")
    if not form.get("phone"): raise HTTPException(status_code=400, detail="El teléfono es obligatorio.")
    if not form.get("parentEmail"): raise HTTPException(status_code=400, detail="El email del tutor es obligatorio.")
    if not form.get("city"): raise HTTPException(status_code=400, detail="La ciudad es obligatoria.")
    if not form.get("foundUs"): raise HTTPException(status_code=400, detail="Indica cómo nos conociste.")
    
    if not form.get("trainingType"): raise HTTPException(status_code=400, detail="Indica el tipo de entrenamiento.")
    if not form.get("commitment"): raise HTTPException(status_code=400, detail="Confirma tu compromiso.")
    if not form.get("videoPermission"): raise HTTPException(status_code=400, detail="Indica el permiso de vídeo.")
    if not form.get("whatsappContent"): raise HTTPException(status_code=400, detail="Indica preferencia de WhatsApp.")
    
    if not form.get("strengths"): raise HTTPException(status_code=400, detail="Indica tus virtudes.")
    if not form.get("weaknesses"): raise HTTPException(status_code=400, detail="Indica tus defectos/mejoras.")
    
    if not form.get("nervesConfidence"): raise HTTPException(status_code=400, detail="Responde sobre nervios/confianza.")
    if not form.get("discomfort"): raise HTTPException(status_code=400, detail="Responde sobre malestar.")
    if not form.get("enjoyment"): raise HTTPException(status_code=400, detail="Responde sobre disfrute/motivación.")
    if not form.get("recovery"): raise HTTPException(status_code=400, detail="Responde sobre recuperación.")
    
    if not form.get("injuries"): raise HTTPException(status_code=400, detail="Indica historial de lesiones.")
    physical_work = form.get("physicalWork")
    if not physical_work: raise HTTPException(status_code=400, detail="Indica si has hecho trabajo físico.")
    if physical_work == "si" and not form.get("physicalWorkDetails"):
        raise HTTPException(status_code=400, detail="Si has hecho trabajo físico, detalla dónde y cuánto tiempo.")
    
    if not form.get("alcohol"): raise HTTPException(status_code=400, detail="Indica consumo de alcohol.")
    if not form.get("smoking"): raise HTTPException(status_code=400, detail="Indica consumo de tabaco.")
    # ---------------------------------
    existing = crud.get_user_by_email(db, email)
    if existing:
        raise HTTPException(status_code=409, detail="Ya existe un usuario con ese email. Inicia sesión.")
    # Store photo content temporarily (before user creation)
    photo_content = None
    photo_ext = None
    player_photo = form.get("playerPhoto")
    is_upload = hasattr(player_photo, 'filename') and hasattr(player_photo, 'read')
    if is_upload and player_photo.filename:
        try:
            photo_content = await player_photo.read()
            if photo_content:
                photo_ext = os.path.splitext(player_photo.filename)[1].lower() or ".jpg"
        except Exception as e:
            print(f"ERROR: Failed to read photo: {e}")
    
    # Create user first
    user_id = crud.create_user(db, name.strip(), email, password, role="alumno", first_name=first_name, last_name=last_name)
    
    # Now save photo with user_ID.ext format
    avatar_path = None
    if photo_content and photo_ext:
        try:
            uploads_dir = BASE_DIR / "app" / "static" / "uploads"
            uploads_dir.mkdir(parents=True, exist_ok=True)
            filename = f"user_{user_id}{photo_ext}"
            file_path = uploads_dir / filename
            with open(file_path, "wb") as f:
                f.write(photo_content)
            avatar_path = f"/static/uploads/{filename}"
        except Exception as e:
            print(f"ERROR: Failed to save photo to disk: {e}")
    
    data: dict[str, str] = {}
    for k, v in form.items():
        if isinstance(v, UploadFile):
            continue
        if v not in (None, "", "null"):
            data[k] = str(v)
    def pick(*keys):
        for k in keys:
            val = data.get(k)
            if val not in (None, "", "null"):
                return val
        return None
    
    # Update profile
    crud.update_user_profile(db, user_id,
        phone=pick("phone", "whatsapp"),
        dni=pick("dni"),
        birth_date=pick("birthDate", "birth_date"),
        city=pick("city"),
        gender=pick("gender"),
        avatar=avatar_path or pick("playerPhoto", "avatar")
    )
    
    # Update sports
    crud.update_user_sports(db, user_id,
        team=pick("currentTeam", "team", "club"),
        category=pick("category"),
        position=pick("currentPosition", "preferredPosition", "position"),
        dominant_foot=pick("dominantFoot"),
        strengths=pick("strengths"),
        weaknesses=pick("weaknesses"),
        training_type=pick("trainingType"),
        injury_history=pick("injuries", "injuryHistory", "injury_history")
    )
    
    # Update health
    crud.update_user_health(db, user_id,
        physical_work=pick("physicalWork"),
        physical_work_details=pick("physicalWorkDetails"),
        smoking=pick("smoking"),
        alcohol=pick("alcohol"),
        recovery=pick("recovery"),
        chest_pain=pick("chestPain"),
        discomfort=pick("discomfort")
    )
    
    # Update consent
    crud.update_user_consent(db, user_id,
        whatsapp_content=pick("whatsappContent"),
        video_permission=pick("videoPermission"),
        privacy_acceptance=pick("privacyAcceptance"),
        data_confirmation=pick("dataConfirmation"),
        agreement=pick("agreement")
    )
    
    # Update guardians
    crud.update_user_guardians(db, user_id,
        occupation=pick("occupation"),
        study_place=pick("studyPlace", "study_place"),
        parent_name=pick("parentName", "parent_name"),
        parent_email=pick("parentEmail", "parent_email")
    )
    
    # Update marketing
    crud.update_user_marketing(db, user_id,
        found_us=pick("foundUs", "found_us"),
        enjoyment=pick("enjoyment"),
        nerves_confidence=pick("nervesConfidence", "nerves_confidence"),
        additional_comments=pick("additionalComments", "additional_comments")
    )

    # --- Statistics Collection ---
    from ..models import estadisticas_crud
    
    # We collect everything relevant for statistics
    estadisticas_crud.crear_estadistica(db,
        user_id=user_id,
        nombre=name,
        email=email,
        sexo=form.get("gender"),
        fecha_nacimiento=form.get("birthDate"),
        ciudad=form.get("city"),
        categoria=form.get("category"),
        equipo_actual=form.get("currentTeam"),
        posicion=form.get("currentPosition"),
        posicion_preferida=form.get("preferredPosition"),
        pierna_dominante=form.get("dominantFoot"),
        ocupacion=form.get("occupation"),
        como_nos_encontro=form.get("foundUs"),
        tipo_entrenamiento=form.get("trainingType"),
        nervios_confianza=form.get("nervesConfidence"),
        malestar=form.get("discomfort"),
        disfrute=form.get("enjoyment"),
        recuperacion=form.get("recovery"),
        alcohol=form.get("alcohol"),
        tabaco=form.get("smoking"),
        dolor_pecho=form.get("chestPain"),
        trabajo_fisico=form.get("physicalWork"),
        permiso_video=form.get("videoPermission"),
        contenido_whatsapp=form.get("whatsappContent")
    )

    return JSONResponse({"ok": True, "redirect": "/login"})
