# routes/notifications.py
from flask import Blueprint, jsonify, render_template, request, abort, current_app
from flask_login import login_required, current_user
from sqlalchemy import or_, desc
from urllib.parse import urlparse, urlunparse
from typing import Optional
from models import db, Notification

notifications_bp = Blueprint("notifications", __name__, url_prefix="/notifications")

# ---------------------------
# Helpers
# ---------------------------

# routes/notifications.py (top)
from urllib.parse import urlparse, urlunparse
from typing import Optional
from flask import current_app, request

def _preferred_scheme() -> str:
    # Use config if set, else detect from proxy header/request
    return (current_app.config.get("PREFERRED_URL_SCHEME")
            or ("https" if request.headers.get("X-Forwarded-Proto", "").lower() == "https"
                else request.scheme or "https")).lower()

def _canonical_host_and_scheme():
    """
    Returns (scheme, host) in priority:
    1) EXTERNAL_BASE_URL (scheme+host)
    2) SERVER_NAME (host) + PREFERRED_URL_SCHEME (scheme)
    3) request.host + detected scheme
    """
    external = (current_app.config.get("EXTERNAL_BASE_URL") or "").strip()
    if external:
        p = urlparse(external if "://" in external else f"https://{external}")
        if p.netloc:
            return (p.scheme or _preferred_scheme(), p.netloc)

    server_name = (current_app.config.get("SERVER_NAME") or "").strip()
    if server_name:
        return (_preferred_scheme(), server_name)

    return (_preferred_scheme(), request.host)

def _canonicalize_link(raw: Optional[str]) -> Optional[str]:
    if not raw:
        return None

    raw = raw.strip()
    scheme, host = _canonical_host_and_scheme()

    # Absolute URL?
    if raw.lower().startswith(("http://", "https://")):
        p = urlparse(raw)
        p = p._replace(scheme=scheme, netloc=host)
        return urlunparse(p)

    # Site-absolute path
    if raw.startswith("/"):
        return f"{scheme}://{host}{raw}"

    # Relative path
    return f"{scheme}://{host}/{raw.lstrip('/')}"
def _base_query_for_employee(emp):
    """Return notifications for this employee + broadcasts (employee_id IS NULL)."""
    return Notification.query.filter(
        or_(
            Notification.employee_id == emp.id,
            Notification.employee_id.is_(None)
        )
    )

# ---------------------------
# Routes
# ---------------------------

@notifications_bp.get("/unread")
@login_required
def unread():
    limit = max(1, min(int(request.args.get("limit", 10)), 50))
    q = (_base_query_for_employee(current_user)
         .filter(Notification.is_read.is_(False))
         .order_by(desc(Notification.created_at)))
    rows = q.limit(limit).all()
    return jsonify([
        {
            "id": n.id,
            "title": n.title,
            "message": n.message,
            "type": n.type,
            "link": _canonicalize_link(n.link),
            "created_at": n.created_at.strftime("%Y-%m-%d %H:%M")
        } for n in rows
    ])

@notifications_bp.get("/count")
@login_required
def count():
    c = (_base_query_for_employee(current_user)
         .filter(Notification.is_read.is_(False))
         .count())
    return jsonify({"count": c})

@notifications_bp.post("/mark-read/<int:notif_id>")
@login_required
def mark_read(notif_id):
    n = Notification.query.get_or_404(notif_id)
    if not (n.employee_id == current_user.id or n.employee_id is None):
        abort(403)
    n.is_read = True
    db.session.commit()
    return jsonify({"ok": True})

@notifications_bp.post("/mark-all-read")
@login_required
def mark_all_read():
    q = (_base_query_for_employee(current_user)
         .filter(Notification.is_read.is_(False)))
    updated = q.update({Notification.is_read: True}, synchronize_session=False)
    db.session.commit()
    return jsonify({"ok": True, "updated": updated})

@notifications_bp.get("")
@login_required
def inbox():
    page = request.args.get("page", 1, type=int)
    per_page = request.args.get("per_page", 20, type=int)
    q = _base_query_for_employee(current_user).order_by(desc(Notification.created_at))
    pag = q.paginate(page=page, per_page=per_page, error_out=False)

    items = []
    for n in pag.items:
        items.append({
            "id": n.id,
            "title": n.title,
            "message": n.message,
            "type": n.type,
            "link": _canonicalize_link(n.link),
            "is_read": n.is_read,
            "created_at": n.created_at,
        })

    return render_template("notifications/inbox.html", pagination=pag, items=items)