"""Admin blueprint — user management, permissions, audit log."""
from __future__ import annotations
import logging, os, time
from flask import Blueprint, jsonify, render_template, request, session
from services.rbac_decorators import admin_required, login_required
import services.rbac_service as rbac

logger = logging.getLogger("apex.admin")
admin_bp = Blueprint("admin", __name__)

def _send_email(to, subject, body):
    try:
        import smtplib
        from email.mime.text import MIMEText
        host = os.getenv("SMTP_HOST",""); user = os.getenv("SMTP_USER",""); pwd = os.getenv("SMTP_PASS","")
        if not host: return False
        msg = MIMEText(body, "html"); msg["Subject"]=subject; msg["From"]=user; msg["To"]=to
        with smtplib.SMTP_SSL(host, 465) as s: s.login(user, pwd); s.sendmail(user,[to],msg.as_string())
        return True
    except Exception as e: logger.warning("[Email] %s",e); return False

def _send_set_password(email, name, url):
    return _send_email(email, "APEX — Set Your Password", f"<p>Hi {name},</p><p><a href='{url}'>Click here to set your password</a></p><p>Link expires in 24h.</p>")

def _send_rejection(email, name, reason):
    return _send_email(email, "APEX — Access Request Update", f"<p>Hi {name}, your request was not approved. Reason: {reason}</p>")

def _user_dict(u):
    return {"id":u.id,"email":u.email,"full_name":getattr(u,"full_name",getattr(u,"name","")),"department":getattr(u,"department",""),"role":u.role,"status":u.status,"approved_by":getattr(u,"approved_by",None),"has_password":getattr(u,"has_password",False),"created_at":getattr(u,"created_at",None),"approved_at":getattr(u,"approved_at",None)}

def _fmt_ts(ts):
    if not ts: return ""
    import datetime
    try:
        from zoneinfo import ZoneInfo
        return datetime.datetime.fromtimestamp(float(ts),tz=ZoneInfo("Asia/Kolkata")).strftime("%d %b %Y, %H:%M")
    except: return str(ts)

# ── UI ────────────────────────────────────────────────────────────────────────
@admin_bp.route("/")
@login_required
@admin_required
def index(): return render_template("admin/index.html")

# ── Users ─────────────────────────────────────────────────────────────────────
@admin_bp.route("/users")
@login_required
@admin_required
def api_users():
    users = rbac.get_all_users(status=request.args.get("status",""))
    return jsonify({"users":[_user_dict(u) for u in users]})

@admin_bp.route("/users/pending")
@login_required
@admin_required
def api_pending():
    result = []
    for u in rbac.get_all_users(status="pending"):
        d = _user_dict(u); d["requested_brands"] = rbac.get_requested_brands(u.id); result.append(d)
    return jsonify({"users":result})

@admin_bp.route("/users/<int:user_id>")
@login_required
@admin_required
def api_user_detail(user_id):
    user = rbac.get_user_by_id(user_id)
    if not user: return jsonify({"error":"User not found"}), 404
    d = _user_dict(user); d["permissions"] = rbac.get_user_permissions(user_id)
    return jsonify(d)

@admin_bp.route("/users/<int:user_id>/approve", methods=["POST"])
@login_required
@admin_required
def api_approve(user_id):
    body = request.get_json() or {}
    ok, msg, token = rbac.approve_user(user_id, session.get("user","admin"), body.get("permissions",[]))
    if not ok: return jsonify({"success":False,"error":msg}), 400
    url = (request.host_url.rstrip("/")+f"/auth/set-password/{token}") if token else None
    if url:
        user = rbac.get_user_by_id(user_id)
        if user: _send_set_password(user.email, user.name, url)
    return jsonify({"success":True,"message":msg,"set_password_url":url})

@admin_bp.route("/users/<int:user_id>/reject", methods=["POST"])
@login_required
@admin_required
def api_reject(user_id):
    body = request.get_json() or {}
    user = rbac.get_user_by_id(user_id)
    ok, msg = rbac.reject_user(user_id, session.get("user","admin"), body.get("reason",""))
    if not ok: return jsonify({"success":False,"error":msg}), 400
    if user: _send_rejection(user.email, user.name, body.get("reason",""))
    return jsonify({"success":True,"message":msg})

@admin_bp.route("/users/<int:user_id>/deactivate", methods=["POST"])
@login_required
@admin_required
def api_deactivate(user_id):
    user = rbac.get_user_by_id(user_id)
    if not user: return jsonify({"success":False,"error":"User not found"}), 404
    if user.email == "admin@rptechindia.com": return jsonify({"success":False,"error":"Cannot deactivate root admin"}), 400
    return jsonify({"success":rbac.set_user_status(user_id,"inactive",session.get("user","admin"))})

@admin_bp.route("/users/<int:user_id>/role", methods=["POST"])
@login_required
@admin_required
def api_change_role(user_id):
    body = request.get_json() or {}
    role = body.get("role","")
    if role not in ("admin","manager","employee"): return jsonify({"success":False,"error":"Invalid role"}), 400
    user = rbac.get_user_by_id(user_id)
    if not user: return jsonify({"success":False,"error":"User not found"}), 404
    if user.email == "admin@rptechindia.com": return jsonify({"success":False,"error":"Cannot change root admin role"}), 400
    ok = rbac.set_user_role(user_id, role, session.get("user","admin"))
    return jsonify({"success":ok,"message":f"Role changed to {role}" if ok else "Failed"})

@admin_bp.route("/users/<int:user_id>/resend-setup", methods=["POST"])
@login_required
@admin_required
def api_resend_setup(user_id):
    ok, msg, token = rbac.resend_set_password_token(user_id, session.get("user","admin"))
    if not ok: return jsonify({"success":False,"error":msg}), 400
    user = rbac.get_user_by_id(user_id)
    if user: _send_set_password(user.email, user.name, request.host_url.rstrip("/")+f"/auth/set-password/{token}")
    return jsonify({"success":True,"message":f"Setup email resent to {user.email if user else user_id}"})

@admin_bp.route("/users/create", methods=["POST"])
@login_required
@admin_required
def api_create_user():
    body = request.get_json() or {}
    email = (body.get("email") or "").strip().lower()
    name = (body.get("full_name") or "").strip()
    role = body.get("role","employee")
    if not name or not email: return jsonify({"success":False,"error":"Name and email required"}), 400
    if role not in ("admin","manager","employee"): return jsonify({"success":False,"error":"Invalid role"}), 400
    ok, msg, token = rbac.create_user_by_admin(email=email,full_name=name,department=body.get("department","").strip(),role=role,admin_email=session.get("user","admin"))
    if not ok: return jsonify({"success":False,"error":msg}), 400
    url = (request.host_url.rstrip("/")+f"/auth/set-password/{token}") if token else None
    if url: _send_set_password(email, name, url)
    return jsonify({"success":True,"message":msg,"set_password_url":url})

# ── Permissions ────────────────────────────────────────────────────────────────
@admin_bp.route("/users/<int:user_id>/permissions", methods=["GET"])
@login_required
@admin_required
def api_get_permissions(user_id):
    user = rbac.get_user_by_id(user_id)
    if not user: return jsonify({"error":"User not found"}), 404
    return jsonify({"permissions":rbac.get_user_permissions(user_id),"effective":rbac.get_user_effective_permissions(user.email)})

@admin_bp.route("/users/<int:user_id>/permissions", methods=["POST"])
@login_required
@admin_required
def api_assign_permissions(user_id):
    body = request.get_json() or {}
    perms = body.get("permissions",[])
    count = rbac.assign_permissions(user_id, perms, session.get("user","admin"))
    return jsonify({"success":True,"assigned":count,"permissions":perms})

@admin_bp.route("/users/<int:user_id>/permissions/<path:perm_name>", methods=["DELETE"])
@login_required
@admin_required
def api_revoke_permission(user_id, perm_name):
    ok = rbac.revoke_permission(user_id, perm_name, session.get("user","admin"))
    if not ok: return jsonify({"error":"Permission not found"}), 404
    return jsonify({"success":True,"revoked":perm_name})

@admin_bp.route("/permissions")
@login_required
@admin_required
def api_permissions():
    return jsonify({"permissions":[{"name":n,"module":m,"action":a,"description":""} for n,m,a in rbac.DEFAULT_PERMISSIONS]})

# ── Audit ─────────────────────────────────────────────────────────────────────
@admin_bp.route("/audit")
@login_required
@admin_required
def api_audit():
    limit = min(int(request.args.get("limit",100)),500)
    return jsonify({"logs":[{"action":r.get("action"),"performed_by":r.get("actor_email"),"target_user":r.get("target_email"),"details":r.get("detail"),"created_at":r.get("created_at")} for r in rbac.get_audit_log(limit=limit)]})

# ── Health ────────────────────────────────────────────────────────────────────
@admin_bp.route("/system/health")
@login_required
@admin_required
def api_system_health():
    import extensions as ext
    try:
        all_users = rbac.get_all_users()
        rbac_stats = {"total_users":len(all_users),"active_users":sum(1 for u in all_users if u.status=="active"),"pending_users":sum(1 for u in all_users if u.status=="pending"),"admin_count":sum(1 for u in all_users if u.role=="admin")}
    except Exception as e: rbac_stats = {"error":str(e)}
    return jsonify({"status":"ok","rbac":rbac_stats,"checks":{"redis":"ok" if (ext.redis_client and ext.redis_client.enabled) else "fallback","sap_hana":"configured" if os.getenv("HANA_HOST") else "not_configured"},"smtp":{"host":os.getenv("SMTP_HOST",""),"configured":bool(os.getenv("SMTP_HOST"))},"timestamp":time.time()})

@admin_bp.route("/system/test-email", methods=["POST"])
@login_required
@admin_required
def api_test_email():
    to = (request.get_json() or {}).get("to") or session.get("user","")
    if not to: return jsonify({"success":False,"error":"No recipient"}), 400
    ok = _send_email(to,"[Apex] SMTP test","<p>SMTP is working correctly.</p>")
    return jsonify({"success":ok,"sent_to":to,"smtp_host":os.getenv("SMTP_HOST","not set")})

# ── Brands ────────────────────────────────────────────────────────────────────
@admin_bp.route("/users/<int:user_id>/brands", methods=["GET"])
@login_required
@admin_required
def api_get_brands(user_id):
    user = rbac.get_user_by_id(user_id)
    if not user: return jsonify({"error":"User not found"}), 404
    return jsonify({"assigned":rbac.get_user_brands(user_id),"requested":rbac.get_requested_brands(user_id)})

@admin_bp.route("/users/<int:user_id>/brands", methods=["POST"])
@login_required
@admin_required
def api_assign_brands(user_id):
    body = request.get_json() or {}
    rbac.assign_brands(user_id, body.get("brands",[]), session.get("user","admin"))
    return jsonify({"success":True,"assigned":body.get("brands",[])})

@admin_bp.route("/notifications/count")
@login_required
@admin_required
def api_notifications_count():
    return jsonify({"unread_count":len(rbac.get_all_users(status="pending"))})