from flask import request
from flask_jwt_extended import (
    create_access_token,
    create_refresh_token,
    get_jwt_identity,
    jwt_required,
    set_access_cookies,
    set_refresh_cookies,
    unset_jwt_cookies,
)
from app.api import api_bp
from app.extensions import db
from app.models.user import User
from app.services.auth_service import register_user, reset_password
from app.services.tracking_service import start_session, end_session
from app.utils.response import ok, fail


@api_bp.post("/auth/register")
def auth_register():
    user, error = register_user(request.json or {})
    if error:
        return fail(error, 400)
    return ok({"id": user.id, "username": user.username}, "Registration successful")


@api_bp.post("/auth/login")
def auth_login():
    data = request.json or {}
    username_or_email = data.get("username")
    password = data.get("password")

    user = User.query.filter(
        (User.username == username_or_email) | (User.email == username_or_email)
    ).first()

    if not user or not user.check_password(password):
        return fail("Invalid username/email or password", 401)
    if user.account_status != "Approved":
        return fail("Your account is not approved. Please contact the administrator.", 403)

    user_session = start_session(user.id)

    access_token = create_access_token(identity=user.id, additional_claims={"session_id": user_session.session_id})
    refresh_token = create_refresh_token(identity=user.id)

    response, _status = ok(
        {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "full_name": user.full_name,
            "access_level": user.access_level,
        },
        "Login successful",
    )
    set_access_cookies(response, access_token)
    set_refresh_cookies(response, refresh_token)
    return response


@api_bp.post("/auth/logout")
@jwt_required()
def auth_logout():
    identity = get_jwt_identity()
    # Session handling is best-effort
    user = User.query.get(identity)
    if user:
        for session in user.sessions:
            if session.is_active:
                end_session(session.session_id)
                break

    response, _status = ok(message="Logout successful")
    unset_jwt_cookies(response)
    return response


@api_bp.post("/auth/forgot-password")
def auth_forgot_password():
    data = request.json or {}
    email = data.get("email")
    user, error = reset_password(email)
    if error:
        return fail(error, 404)
    return ok(message="Check your email for your new password.")


@api_bp.get("/auth/me")
@jwt_required()
def auth_me():
    user = User.query.get(get_jwt_identity())
    if not user:
        return fail("User not found", 404)
    return ok(
        {
            "id": user.id,
            "username": user.username,
            "email": user.email,
            "full_name": user.full_name,
            "access_level": user.access_level,
            "account_status": user.account_status,
        }
    )


@api_bp.post("/auth/change-password")
@jwt_required()
def auth_change_password():
    user = User.query.get(get_jwt_identity())
    if not user:
        return fail("User not found", 404)

    data = request.json or {}
    current_password = (data.get("current_password") or "").strip()
    new_password = (data.get("new_password") or "").strip()

    if not current_password or not new_password:
        return fail("Current password and new password are required", 400)
    if not user.check_password(current_password):
        return fail("Current password is incorrect", 400)
    if len(new_password) < 6:
        return fail("New password must be at least 6 characters", 400)

    user.set_password(new_password)
    db.session.commit()
    return ok(message="Password updated")
