from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi import status
from sqlalchemy.orm import Session as DBSession
from pathlib import Path
import shutil
from typing import Optional
from pydantic import BaseModel, EmailStr, field_validator

from app.core.database import SessionLocal
from app.core.auth import get_current_user
from app.models.user import User

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

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

# -----------------------------
# 1) Neuer PIN anfordern (Mock)
# -----------------------------
@router.post("/request-new-pin", status_code=status.HTTP_202_ACCEPTED)
def request_new_pin(current_user: User = Depends(get_current_user)):
    return {"status": "queued", "message": "PIN request queued (mock)"}

# -----------------------------
# 2) Profil-Avatar hochladen (persistiert avatar_url)
# -----------------------------
UPLOAD_DIR = Path("media/avatars")

@router.post("/avatar", status_code=status.HTTP_200_OK)
def upload_avatar(
    file: UploadFile = File(...),
    db: DBSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    UPLOAD_DIR.mkdir(parents=True, exist_ok=True)

    filename = file.filename or "avatar"
    ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
    if ext not in {"png", "jpg", "jpeg", "webp", "gif", ""}:
        raise HTTPException(status_code=400, detail="Unsupported file type")
    final_ext = ext if ext else "png"

    dest = UPLOAD_DIR / f"{current_user.id}.{final_ext}"
    with dest.open("wb") as out:
        shutil.copyfileobj(file.file, out)

    # User in diese Session laden
    u = db.query(User).filter(User.id == current_user.id).first()
    if not u:
        raise HTTPException(status_code=404, detail="User not found")

    u.avatar_url = f"/media/avatars/{u.id}.{final_ext}"
    db.commit()
    db.refresh(u)

    import time
    return {
        "status": "ok",
        "avatar_url": f"{u.avatar_url}?t={int(time.time())}",
        "path": str(dest),
    }

# -----------------------------
# 3) Eigene Basisdaten ändern (inkl. PayPal + Passwort)
# -----------------------------
class ProfileUpdate(BaseModel):
    alias: Optional[str] = None
    paypal_email: Optional[EmailStr] = None
    visible_in_stats: Optional[bool] = None
    public_stats: Optional[bool] = None 
    
    # Passwortwechsel
    current_password: Optional[str] = None
    new_password: Optional[str] = None

    @field_validator("new_password")
    @classmethod
    def _min_len_pw(cls, v):
        if v is not None and len(v) < 8:
            raise ValueError("Password too short (min. 8)")
        return v

@router.put("/me", response_model=dict)
def update_profile(
    payload: ProfileUpdate,
    db: DBSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    u = db.query(User).filter(User.id == current_user.id).first()
    if not u:
        raise HTTPException(status_code=404, detail="User not found")

    changed = False

    # Alias
    if payload.alias is not None:
        u.alias = payload.alias
        changed = True

    # PayPal-Mail
    if payload.paypal_email is not None:
        u.paypal_email = str(payload.paypal_email).lower()
        changed = True

    # Sichtbarkeit (Kompatibilität: beide Keys akzeptieren)
    flag = payload.public_stats if payload.public_stats is not None else payload.visible_in_stats
    if flag is not None:
        u.public_stats = bool(flag)
        changed = True

    # Passwortwechsel nur mit current_password
    if payload.new_password is not None:
        from passlib.context import CryptContext
        pwd = CryptContext(schemes=["bcrypt"], deprecated="auto")

        # Wenn ein Passwort gesetzt ist, muss current_password mitgeschickt werden
        if getattr(u, "hashed_password", None):
            if not payload.current_password:
                raise HTTPException(status_code=400, detail="Current password required")
            if not pwd.verify(payload.current_password, u.hashed_password):
                raise HTTPException(status_code=400, detail="Current password invalid")

        u.hashed_password = pwd.hash(payload.new_password)
        changed = True

    if changed:
        db.commit()
        db.refresh(u)

    return {"status": "ok"}
