import secrets
from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session

from app.api.deps import get_current_user
from app.core.database import get_db
from app.core.security import create_access_token, hash_password, verify_password
from app.models import Plan, Profile, User
from app.schemas import LoginIn, RegisterIn, TokenOut, UserOut
from app.services.entitlements import assign_plan, get_plan_for_user
from app.services.seed import DEFAULT_SKILLS

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


def _user_out(db, user: User) -> UserOut:
    plan = get_plan_for_user(db, user)
    data = UserOut.model_validate(user)
    data.plan_key = plan.key
    data.plan_name = plan.name
    return data


def _ensure_referral(user: User) -> None:
    if not user.referral_code:
        user.referral_code = secrets.token_urlsafe(6).replace("-", "")[:10].upper()


@router.post("/login", response_model=TokenOut)
def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
    user = db.query(User).filter(User.email == form_data.username).first()
    if not user or not verify_password(form_data.password, user.hashed_password):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Credenciales incorrectas")
    return TokenOut(access_token=create_access_token(user.id))


@router.post("/login-json", response_model=TokenOut)
def login_json(payload: LoginIn, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.email == payload.email).first()
    if not user or not verify_password(payload.password, user.hashed_password):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Credenciales incorrectas")
    return TokenOut(access_token=create_access_token(user.id))


@router.post("/register", response_model=UserOut)
def register(payload: RegisterIn, db: Session = Depends(get_db)):
    if not payload.privacy_accepted:
        raise HTTPException(400, "Debes aceptar la política de privacidad y condiciones")
    if db.query(User).filter(User.email == payload.email).first():
        raise HTTPException(status_code=400, detail="Email ya registrado")
    user = User(
        email=payload.email,
        name=payload.name,
        hashed_password=hash_password(payload.password),
        is_admin=False,
        privacy_accepted_at=datetime.now(timezone.utc),
        marketing_consent=bool(payload.marketing_consent),
        referred_by=(payload.referral_code or "").strip().upper() or None,
        utm_source=payload.utm_source,
        utm_medium=payload.utm_medium,
        utm_campaign=payload.utm_campaign,
    )
    _ensure_referral(user)
    db.add(user)
    db.flush()
    db.add(
        Profile(
            user_id=user.id,
            skills=list(DEFAULT_SKILLS),
            keywords=["empleo", "remoto", "teletrabajo"],
            desired_roles=[],
            job_categories=["general"],
            employment_types=["full_time", "remote", "hybrid"],
            remote_only=False,
            english_fluent=False,
            salary_min=25000,
            salary_currency="EUR",
            target_countries=["ES", "EU"],
            location="Spain",
            timezone="Europe/Madrid",
        )
    )
    free = db.query(Plan).filter(Plan.key == "free").first()
    if free:
        assign_plan(db, user, free, note="Registro")
    else:
        db.commit()
    db.refresh(user)
    return _user_out(db, user)


@router.get("/me", response_model=UserOut)
def me(user: User = Depends(get_current_user), db: Session = Depends(get_db)):
    _ensure_referral(user)
    db.commit()
    return _user_out(db, user)
