from flask import Blueprint, render_template, request, current_app
from jinja2_fragments import render_block
from flask_htmx import HTMX

endpoints_bp = Blueprint('endpoints', __name__, url_prefix='/endpoints')
htmx = HTMX()

def _get_routes(app):
    """Helper function to extract routes from the Flask app object."""
    routes = []
    for rule in app.url_map.iter_rules():
        # Exclude static routes and HEAD/OPTIONS methods
        if rule.endpoint == 'static':
            continue
        methods = ', '.join(sorted(rule.methods - {'HEAD', 'OPTIONS'}))
        route_info = {
            'endpoint': rule.endpoint,
            'url': rule.rule,
            'methods': methods,
            'view_func': app.view_functions[rule.endpoint].__name__,
            'doc': app.view_functions[rule.endpoint].__doc__
        }
        routes.append(route_info)
    return routes

@endpoints_bp.route('/')
def list_endpoints():
    """
    Lists all API endpoints available in the Flask application.

    This endpoint retrieves all registered routes, excluding static routes,
    and displays their details such as endpoint name, URL, allowed HTTP methods,
    view function name, and a brief description.
    """
    # Pass current_app to the helper function
    routes = _get_routes(current_app)

    if htmx:
        # Assuming 'endpoints.html' uses a block named 'content'
        return render_block(current_app.jinja_env, 'endpoints.html', 'content', routes=routes)
    return render_template('endpoints.html', routes=routes)

@endpoints_bp.route('/search')
def search_endpoints():
    """Searches and filters endpoints based on a query."""
    # Pass current_app to the helper function
    routes = _get_routes(current_app)
    search = request.args.get('search', '').lower()
    if search:
        routes = [
            route for route in routes
            if search in route['endpoint'].lower()
            or search in route['url'].lower()
            or search in route['methods'].lower()
            or search in route['view_func'].lower()
            or (route.get('doc') and search in route['doc'].lower()) # Safer access to 'doc'
        ]

    # Renders the partial table
    return render_template('partials/endpoints_table.html', routes=routes)