from functools import wraps

from flask import Blueprint, render_template, redirect, url_for, flash, abort
from flask_login import login_required, current_user

from app.extensions import db
from app.models import Sponsor, User, IntakeEvent
from app.admin.forms import SponsorForm, StaffUserForm
from app.analytics import queries as analytics

admin_bp = Blueprint("admin", __name__, url_prefix="/admin", template_folder="../templates/admin")


def admin_required(view):
    @wraps(view)
    def wrapped(*args, **kwargs):
        if not current_user.is_authenticated or not current_user.is_admin():
            abort(403)
        return view(*args, **kwargs)

    return wrapped


@admin_bp.route("/")
@login_required
@admin_required
def index():
    return render_template("admin/index.html", stats=analytics.summary_stats())


@admin_bp.route("/analytics")
@login_required
@admin_required
def analytics_dashboard():
    return render_template(
        "admin/analytics.html",
        stats=analytics.summary_stats(),
        patients_by_age=analytics.patients_by_age_range(),
        top_categories=analytics.top_condition_categories(),
        diagnosis_matrix=analytics.diagnosis_age_matrix(),
        top_medications=analytics.top_medications(),
        top_doctors=analytics.top_doctors(),
        top_entities=analytics.top_health_entities(),
        monthly_trend=analytics.monthly_event_trend(),
        prescription_patterns=analytics.prescription_patterns(),
        senior_share=analytics.senior_share(),
        patients_by_country=analytics.patients_by_country(),
        patients_by_city=analytics.patients_by_city(),
        relationship_distribution=analytics.caregiver_relationship_distribution(),
        profiles_histogram=analytics.profiles_per_caregiver_histogram(),
        caregiver_summary=analytics.caregiver_accounts_summary(),
    )


@admin_bp.route("/recepcion")
@login_required
@admin_required
def intake_log():
    events = IntakeEvent.query.order_by(IntakeEvent.received_at.desc()).limit(200).all()
    unmatched_count = IntakeEvent.query.filter_by(
        status=IntakeEvent.STATUS_UNMATCHED_SENDER
    ).count()
    return render_template("admin/intake_log.html", events=events, unmatched_count=unmatched_count)


@admin_bp.route("/patrocinadores")
@login_required
@admin_required
def sponsors_list():
    sponsors = Sponsor.query.order_by(Sponsor.created_at.desc()).all()
    return render_template("admin/sponsors_list.html", sponsors=sponsors)


@admin_bp.route("/patrocinadores/nuevo", methods=["GET", "POST"])
@login_required
@admin_required
def sponsors_new():
    form = SponsorForm()
    if form.validate_on_submit():
        sponsor = form.populate_sponsor()
        db.session.add(sponsor)
        db.session.commit()
        flash("Patrocinador registrado.", "success")
        return redirect(url_for("admin.sponsors_list"))

    return render_template("admin/sponsor_form.html", form=form)


@admin_bp.route("/usuarios")
@login_required
@admin_required
def staff_list():
    staff = User.query.filter_by(role="admin").order_by(User.created_at.desc()).all()
    return render_template("admin/staff_list.html", staff=staff)


@admin_bp.route("/usuarios/nuevo", methods=["GET", "POST"])
@login_required
@admin_required
def staff_new():
    form = StaffUserForm()
    if form.validate_on_submit():
        if User.query.filter_by(email=form.email.data.lower()).first():
            flash("Ya existe una cuenta con ese correo.", "danger")
            return render_template("admin/staff_form.html", form=form)

        user = User(email=form.email.data.lower(), role="admin")
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash(
            f"Cuenta de administrador creada para {user.email}. "
            "Comunícale la contraseña temporal por un canal seguro.",
            "success",
        )
        return redirect(url_for("admin.staff_list"))

    return render_template("admin/staff_form.html", form=form)


@admin_bp.route("/usuarios/<int:user_id>/toggle", methods=["POST"])
@login_required
@admin_required
def staff_toggle(user_id):
    user = db.session.get(User, user_id)
    if not user or user.role != "admin":
        abort(404)
    if user.id == current_user.id:
        flash("No puedes desactivar tu propia cuenta.", "warning")
        return redirect(url_for("admin.staff_list"))

    user.is_active_account = not user.is_active_account
    db.session.commit()
    flash(
        f"Cuenta {'activada' if user.is_active_account else 'desactivada'}: {user.email}",
        "success",
    )
    return redirect(url_for("admin.staff_list"))
