from datetime import datetime

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

from app.auth.access import roles_required
from app.extensions import db
from app.models import ActivityRegistration, ManagerApprovalHistory, ManagerApprovalRequest
from app.models.enums import ApprovalStatus, RegistrationStatus
from app.notifications.service import NotificationService

bp = Blueprint("manager", __name__, url_prefix="/manager")
MANAGER_ROLES = ("MANAGER", "SUPER_ADMIN", "PIRAMAL_ADMIN", "INDIAISUS_ADMIN")


@bp.route("/approvals")
@roles_required(*MANAGER_ROLES)
def approvals():
    employee = current_user.employee
    pending = []
    history = []
    if employee:
        pending = ManagerApprovalRequest.query.filter_by(manager_id=employee.id, status=ApprovalStatus.PENDING).order_by(ManagerApprovalRequest.requested_at).all()
        history = ManagerApprovalRequest.query.filter(
            ManagerApprovalRequest.manager_id == employee.id,
            ManagerApprovalRequest.status != ApprovalStatus.PENDING,
        ).order_by(ManagerApprovalRequest.decided_at.desc()).limit(20).all()
    return render_template("manager/approvals.html", pending=pending, history=history)


@bp.route("/approvals/<int:request_id>", methods=["GET", "POST"])
@roles_required(*MANAGER_ROLES)
def approval_detail(request_id):
    approval = db.session.get(ManagerApprovalRequest, request_id)
    if not approval:
        abort(404)
    if not current_user.has_role("SUPER_ADMIN", "PIRAMAL_ADMIN", "INDIAISUS_ADMIN"):
        if not current_user.employee or approval.manager_id != current_user.employee.id:
            abort(403)

    if request.method == "POST":
        action = request.form.get("action")
        old_status = approval.status
        if old_status != ApprovalStatus.PENDING:
            flash("This request has already been decided.", "warning")
            return redirect(url_for("manager.approval_detail", request_id=approval.id))

        if action == "approve":
            activity = approval.registration.activity
            confirmed_count = ActivityRegistration.query.filter(
                ActivityRegistration.activity_id == activity.id,
                ActivityRegistration.id != approval.registration_id,
                ActivityRegistration.status.in_([
                    RegistrationStatus.REGISTERED,
                    RegistrationStatus.CONFIRMED,
                    RegistrationStatus.ATTENDED,
                    RegistrationStatus.COMPLETED,
                ]),
            ).count()
            if activity.capacity and confirmed_count >= activity.capacity:
                flash("This activity reached capacity while the request was pending. Approval cannot be completed.", "danger")
                return redirect(url_for("manager.approval_detail", request_id=approval.id))
            approval.status = ApprovalStatus.APPROVED
            approval.registration.approval_status = ApprovalStatus.APPROVED
            approval.registration.status = RegistrationStatus.CONFIRMED
            NotificationService.create_in_app(
                approval.employee_id,
                "MANAGER_APPROVAL_APPROVED",
                "Volunteering request approved",
                f"Your request for {activity.title} has been approved.",
                url_for("employee.my_seva"),
            )
        elif action == "decline":
            reason = request.form.get("remarks", "").strip()
            if not reason:
                flash("A reason is required when declining a request.", "danger")
                return redirect(url_for("manager.approval_detail", request_id=approval.id))
            approval.status = ApprovalStatus.DECLINED
            approval.registration.approval_status = ApprovalStatus.DECLINED
            approval.registration.status = RegistrationStatus.CANCELLED
            NotificationService.create_in_app(
                approval.employee_id,
                "MANAGER_APPROVAL_DECLINED",
                "Volunteering request declined",
                f"Your request for {approval.registration.activity.title} was declined. Reason: {reason}",
                url_for("employee.my_seva"),
            )
        else:
            flash("Invalid action.", "danger")
            return redirect(url_for("manager.approval_detail", request_id=approval.id))

        approval.manager_response = request.form.get("remarks", "").strip()
        approval.decided_at = datetime.utcnow()
        db.session.add(ManagerApprovalHistory(
            approval_request_id=approval.id,
            action=action.upper(),
            from_status=old_status,
            to_status=approval.status,
            acted_by_user_id=current_user.id,
            remarks=approval.manager_response,
        ))
        db.session.commit()
        flash(f"Request {approval.status.lower()}.", "success")
        return redirect(url_for("manager.approvals"))

    return render_template("manager/approval_detail.html", approval=approval)
