# Copyright (c) 2023-present Pi Dash Software, Inc. and contributors
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.

"""
Schema processing hooks for drf-spectacular OpenAPI generation.

This module provides preprocessing and postprocessing functions that modify
the generated OpenAPI schema to apply custom filtering, tagging, and other
transformations.
"""


def preprocess_filter_api_v1_paths(endpoints):
    """
    Filter OpenAPI endpoints to only include /api/v1/ paths and exclude PUT methods.
    """
    filtered = []
    for path, path_regex, method, callback in endpoints:
        # Only include paths that start with /api/v1/ and exclude PUT methods
        if path.startswith("/api/v1/") and method.upper() != "PUT" and "server" not in path.lower():
            filtered.append((path, path_regex, method, callback))
    return filtered


def generate_operation_summary(method, path, tag):
    """
    Generate a human-readable summary for an operation.
    """
    # Extract the main resource from the path
    path_parts = [part for part in path.split("/") if part and not part.startswith("{")]

    if len(path_parts) > 0:
        resource = path_parts[-1].replace("-", " ").title()
    else:
        resource = tag

    # Generate summary based on method
    method_summaries = {
        "GET": f"Retrieve {resource}",
        "POST": f"Create {resource}",
        "PATCH": f"Update {resource}",
        "DELETE": f"Delete {resource}",
    }

    # Handle specific cases
    if "archive" in path.lower():
        if method == "POST":
            return f"Archive {tag.rstrip('s')}"
        elif method == "DELETE":
            return f"Unarchive {tag.rstrip('s')}"

    if "transfer" in path.lower():
        return f"Transfer {tag.rstrip('s')}"

    return method_summaries.get(method, f"{method} {resource}")


def postprocess_project_id_dual_form(result, generator, request, public):
    """Annotate project path parameters that now accept either a project UUID
    or a workspace-scoped slug.

    The URL converters were widened from ``<uuid:project_id>`` to
    ``<str:project_id>`` (and the project-detail ``<uuid:pk>`` likewise) so the
    backend accepts either form transparently. Spectacular generates the
    parameter as a plain string from the converter; this hook updates the
    description and ``examples`` so OpenAPI consumers know both forms are
    valid without us having to decorate every endpoint individually.
    """
    description = (
        "Either the project's UUID or its workspace-scoped identifier (e.g. ``ENG``). "
        "Identifier matching is case-insensitive."
    )

    for path, path_item in (result.get("paths") or {}).items():
        if "{project_id}" not in path and "/projects/{pk}/" not in path:
            continue
        for method, operation in path_item.items():
            if not isinstance(operation, dict):
                continue
            for param in operation.get("parameters", []) or []:
                if param.get("in") != "path":
                    continue
                name = param.get("name")
                if name == "project_id" or (name == "pk" and "/projects/{pk}/" in path):
                    param["description"] = description
                    schema = param.setdefault("schema", {})
                    schema.pop("format", None)
                    schema["type"] = "string"
                    param["examples"] = {
                        "uuid": {"value": "00000000-0000-0000-0000-000000000000", "summary": "UUID form"},
                        "slug": {"value": "ENG", "summary": "Workspace-scoped identifier"},
                    }
    return result
