from flask import Blueprint, flash, jsonify, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required

from app import db, log_event, track_event
from app.models import Client, ClientNote, Settings
from app.utils.db import safe_commit
from app.utils.module_registry import ModuleRegistry

client_notes_bp = Blueprint("client_notes", __name__)


@client_notes_bp.before_request
def _enforce_clients_module():
    """Client notes are part of Clients; allow admins only when disabled."""
    if not current_user or not getattr(current_user, "is_authenticated", False):
        return None

    settings = Settings.get_settings()
    if ModuleRegistry.is_enabled("clients", settings, current_user):
        return None

    flash(_("Clients module is disabled by the administrator."), "warning")
    return redirect(url_for("main.dashboard"))


@client_notes_bp.route("/clients/<int:client_id>/notes/create", methods=["POST"])
@login_required
def create_note(client_id):
    """Create a new note for a client"""
    # Verify client exists first (before try block to let 404 abort properly)
    client = Client.query.get_or_404(client_id)

    try:
        content = request.form.get("content", "").strip()
        is_important = request.form.get("is_important", "false").lower() == "true"

        # Validation
        if not content:
            flash(_("Note content cannot be empty"), "error")
            return redirect(url_for("clients.view_client", client_id=client_id))

        # Create the note
        note = ClientNote(content=content, user_id=current_user.id, client_id=client_id, is_important=is_important)

        db.session.add(note)
        if safe_commit("create_client_note", {"client_id": client_id}):
            # Log note creation
            log_event("client_note.created", user_id=current_user.id, client_note_id=note.id, client_id=client_id)
            track_event(current_user.id, "client_note.created", {"note_id": note.id, "client_id": client_id})
            flash(_("Note added successfully"), "success")
        else:
            flash(_("Error adding note"), "error")

    except ValueError as e:
        flash(_("Error adding note: %(error)s", error=str(e)), "error")
    except Exception as e:
        flash(_("Error adding note: %(error)s", error=str(e)), "error")

    # Redirect back to the client page
    return redirect(url_for("clients.view_client", client_id=client_id))


@client_notes_bp.route("/clients/<int:client_id>/notes/<int:note_id>/edit", methods=["GET", "POST"])
@login_required
def edit_note(client_id, note_id):
    """Edit an existing client note"""
    note = ClientNote.query.get_or_404(note_id)

    # Verify note belongs to this client
    if note.client_id != client_id:
        flash(_("Note does not belong to this client"), "error")
        return redirect(url_for("clients.view_client", client_id=client_id))

    # Check permissions
    if not note.can_edit(current_user):
        flash(_("You do not have permission to edit this note"), "error")
        return redirect(url_for("clients.view_client", client_id=client_id))

    if request.method == "POST":
        try:
            content = request.form.get("content", "").strip()
            is_important = request.form.get("is_important", "false").lower() == "true"

            if not content:
                flash(_("Note content cannot be empty"), "error")
                return render_template("client_notes/edit.html", note=note, client_id=client_id)

            note.edit_content(content, current_user, is_important=is_important)

            if not safe_commit("edit_client_note", {"note_id": note_id}):
                flash(_("Error updating note"), "error")
                return render_template("client_notes/edit.html", note=note, client_id=client_id)

            # Log note update
            log_event("client_note.updated", user_id=current_user.id, client_note_id=note.id)
            track_event(current_user.id, "client_note.updated", {"note_id": note.id})

            flash(_("Note updated successfully"), "success")
            return redirect(url_for("clients.view_client", client_id=client_id))

        except ValueError as e:
            flash(_("Error updating note: %(error)s", error=str(e)), "error")
        except Exception as e:
            flash(_("Error updating note: %(error)s", error=str(e)), "error")

    return render_template("client_notes/edit.html", note=note, client_id=client_id)


@client_notes_bp.route("/clients/<int:client_id>/notes/<int:note_id>/delete", methods=["POST"])
@login_required
def delete_note(client_id, note_id):
    """Delete a client note"""
    note = ClientNote.query.get_or_404(note_id)

    # Verify note belongs to this client
    if note.client_id != client_id:
        flash(_("Note does not belong to this client"), "error")
        return redirect(url_for("clients.view_client", client_id=client_id))

    # Check permissions
    if not note.can_delete(current_user):
        flash(_("You do not have permission to delete this note"), "error")
        return redirect(url_for("clients.view_client", client_id=client_id))

    try:
        note_id_for_log = note.id

        db.session.delete(note)

        if not safe_commit("delete_client_note", {"note_id": note_id}):
            flash(_("Error deleting note"), "error")
            return redirect(url_for("clients.view_client", client_id=client_id))

        # Log note deletion
        log_event("client_note.deleted", user_id=current_user.id, client_note_id=note_id_for_log)
        track_event(current_user.id, "client_note.deleted", {"note_id": note_id_for_log})

        flash(_("Note deleted successfully"), "success")

    except Exception as e:
        flash(_("Error deleting note: %(error)s", error=str(e)), "error")

    return redirect(url_for("clients.view_client", client_id=client_id))


@client_notes_bp.route("/clients/<int:client_id>/notes/<int:note_id>/toggle-important", methods=["POST"])
def toggle_important(client_id, note_id):
    """Toggle the important flag on a client note"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    note = ClientNote.query.get_or_404(note_id)

    # Verify note belongs to this client
    if note.client_id != client_id:
        return jsonify({"error": "Note does not belong to this client"}), 400

    # Check permissions
    if not note.can_edit(current_user):
        return jsonify({"error": "Permission denied"}), 403

    try:
        note.is_important = not note.is_important

        if not safe_commit("toggle_important_note", {"note_id": note_id}):
            return jsonify({"error": "Error updating note"}), 500

        # Log note update
        log_event(
            "client_note.importance_toggled",
            user_id=current_user.id,
            client_note_id=note.id,
            is_important=note.is_important,
        )
        track_event(
            current_user.id, "client_note.importance_toggled", {"note_id": note.id, "is_important": note.is_important}
        )

        return jsonify({"success": True, "is_important": note.is_important})

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@client_notes_bp.route("/api/clients/<int:client_id>/notes")
def list_notes(client_id):
    """API endpoint to get notes for a client"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    order_by_important = request.args.get("order_by_important", "false").lower() == "true"

    try:
        # Verify client exists
        client = Client.query.get_or_404(client_id)
        notes = ClientNote.get_client_notes(client_id, order_by_important)

        return jsonify({"success": True, "notes": [note.to_dict() for note in notes]})

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@client_notes_bp.route("/api/client-notes/<int:note_id>")
def get_note(note_id):
    """API endpoint to get a single client note"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    try:
        note = ClientNote.query.get_or_404(note_id)
        return jsonify({"success": True, "note": note.to_dict()})

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@client_notes_bp.route("/api/client-notes/important")
def get_important_notes():
    """API endpoint to get all important client notes"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    client_id = request.args.get("client_id", type=int)

    try:
        notes = ClientNote.get_important_notes(client_id)
        return jsonify({"success": True, "notes": [note.to_dict() for note in notes]})

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@client_notes_bp.route("/api/client-notes/recent")
def get_recent_notes():
    """API endpoint to get recent client notes"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    limit = request.args.get("limit", 10, type=int)

    try:
        notes = ClientNote.get_recent_notes(limit)
        return jsonify({"success": True, "notes": [note.to_dict() for note in notes]})

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@client_notes_bp.route("/api/client-notes/user/<int:user_id>")
def get_user_notes(user_id):
    """API endpoint to get notes by a specific user"""
    # Explicit auth check to avoid redirect behavior from login_required for JSON flows
    if not getattr(current_user, "is_authenticated", False):
        return jsonify({"error": "Authentication required"}), 401
    limit = request.args.get("limit", type=int)

    # Only allow users to see their own notes unless they're admin
    if not current_user.is_admin and current_user.id != user_id:
        return jsonify({"error": "Permission denied"}), 403

    try:
        notes = ClientNote.get_user_notes(user_id, limit)
        return jsonify({"success": True, "notes": [note.to_dict() for note in notes]})

    except Exception as e:
        return jsonify({"error": str(e)}), 500
