from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.orm import Session
from app.database import get_db
from app.models.user import User
from app.models.asim import Asim
from app.schemas.auth import LoginRequest, TokenResponse, RegisterRequest, ChangePasswordRequest
from app.core.security import verify_password, get_password_hash, create_access_token, get_current_user, require_pengurus
from app.core.limiter import limiter
import re

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


def _validate_password_strength(password: str) -> None:
    """Validasi kekuatan password — min 8 karakter, 1 huruf kapital, 1 angka."""
    if len(password) < 8:
        raise HTTPException(status_code=400, detail="Password minimal 8 karakter")
    if not re.search(r'[A-Z]', password):
        raise HTTPException(status_code=400, detail="Password harus ada minimal 1 huruf kapital")
    if not re.search(r'[0-9]', password):
        raise HTTPException(status_code=400, detail="Password harus ada minimal 1 angka")


@router.post("/login", response_model=TokenResponse)
def login(request: Request, body: LoginRequest, db: Session = Depends(get_db)):
    # slowapi wajib parameter pertama bernama `request: Request`
    # body: LoginRequest → berisi username & password dari JSON body

    from app.models.system_setting import SystemSetting
    user = None

    # Coba login pakai username
    if body.username:
        user = db.query(User).filter(User.username == body.username).first()

    # Coba pakai email
    if not user:
        user = db.query(User).filter(User.email == body.username).first()

    # Coba pakai phone
    if not user:
        user = db.query(User).filter(User.phone == body.username).first()

    # Coba pakai no_asim — cari ASIM dulu lalu ambil user-nya
    if not user:
        try:
            no_asim_int = int(body.username)
            asim = db.query(Asim).filter(Asim.no_asim == no_asim_int).first()
            if asim and asim.user_id:
                user = db.query(User).filter(User.id == asim.user_id).first()
        except ValueError:
            pass

    if not user or not verify_password(body.password, user.password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Username atau password salah"
        )
    if not user.is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Akun tidak aktif"
        )

    # Check development mode — skip must_change_password
    dev_mode = db.query(SystemSetting).filter(SystemSetting.key == "development_mode").first()
    is_dev = dev_mode and dev_mode.value == "true"

    token = create_access_token({"sub": str(user.id), "role": user.role})
    asim_id = user.asim.id if user.asim else None
    no_asim = user.asim.no_asim if user.asim else None
    full_name = user.asim.full_name if user.asim else None

    return TokenResponse(
        access_token=token,
        role=user.role,
        user_id=user.id,
        asim_id=asim_id,
        no_asim=no_asim,
        full_name=full_name,
        must_change_password=False if is_dev else user.must_change_password,
    )

@router.post("/change-password")
def change_password(
    request: ChangePasswordRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    # User hanya boleh ganti password diri sendiri
    if current_user.id != request.user_id:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Tidak boleh ganti password orang lain")
    if not verify_password(request.old_password, current_user.password):
        raise HTTPException(status_code=400, detail="Password lama salah")
    _validate_password_strength(request.new_password)
    current_user.password = get_password_hash(request.new_password)
    current_user.must_change_password = False
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan perubahan password")
    return {"message": "Password berhasil diubah"}

@router.post("/register", response_model=TokenResponse)
def register(request: RegisterRequest, db: Session = Depends(get_db), _: User = Depends(require_pengurus)):
    if request.email:
        existing = db.query(User).filter(User.email == request.email).first()
        if existing:
            raise HTTPException(status_code=400, detail="Email sudah terdaftar")
    if request.phone:
        existing = db.query(User).filter(User.phone == request.phone).first()
        if existing:
            raise HTTPException(status_code=400, detail="No HP sudah terdaftar")
    user = User(
        email=request.email,
        phone=request.phone,
        password=get_password_hash(request.password),
        role=request.role
    )
    db.add(user)
    try:
        db.commit()
        db.refresh(user)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal mendaftarkan pengguna baru")
    token = create_access_token({"sub": str(user.id), "role": user.role})
    return TokenResponse(
        access_token=token,
        role=user.role,
        user_id=user.id,
        must_change_password=False,
    )