# Copyright 2025 WhoMeta Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""OpenAPI v3 → UAP Tool list parser.

NOTE: This is a simplified implementation that extracts HTTP operations into generic
`Tool` objects. It assumes an OpenAPI v3 spec is provided as a *dict* (already
parsed from YAML/JSON).

Generated by WhoMeta Unified Agent Protocol SDK
"""
from __future__ import annotations

from typing import Any, Dict, List

from unifiedagentprotocol.models.tool import Tool, ToolParam, OutputSchema
from unifiedagentprotocol.models.common import Trigger


HTTP_METHODS = {"get", "post", "put", "patch", "delete", "options", "head"}


def parse_openapi(spec: Dict[str, Any]) -> List[Tool]:
    """Convert an OpenAPI v3 document into a list of `Tool` definitions."""

    if spec.get("openapi", "").split(".")[0] != "3":
        raise ValueError("Only OpenAPI v3 is supported")

    tools: List[Tool] = []
    base_description = spec.get("info", {}).get("description", "")

    paths: Dict[str, Any] = spec.get("paths", {})
    for path, path_item in paths.items():
        for method, op in path_item.items():
            if method.lower() not in HTTP_METHODS:
                continue

            op_id = op.get("operationId") or f"{method}_{path.strip('/').replace('/', '_')}"
            description = op.get("description") or op.get("summary") or base_description

            parameters: List[ToolParam] = []
            for param in op.get("parameters", []):
                parameters.append(
                    ToolParam(
                        name=param["name"],
                        type=param.get("schema", {}).get("type", "string"),
                        description=param.get("description"),
                        required=param.get("required", False),
                        default=param.get("schema", {}).get("default"),
                        enum=param.get("schema", {}).get("enum"),
                    )
                )

            # Request body (JSON only simplified)
            if "requestBody" in op:
                content = op["requestBody"].get("content", {})
                if "application/json" in content:
                    schema = content["application/json"].get("schema", {})
                    # Flatten top-level object properties into parameters
                    for name, prop in schema.get("properties", {}).items():
                        parameters.append(
                            ToolParam(
                                name=name,
                                type=prop.get("type", "string"),
                                required=name in schema.get("required", []),
                                description=prop.get("description"),
                                default=prop.get("default"),
                                enum=prop.get("enum"),
                            )
                        )

            # Output schema from 200 response JSON
            output = None
            responses = op.get("responses", {})
            if "200" in responses:
                content = responses["200"].get("content", {})
                if "application/json" in content:
                    output = OutputSchema(schema=content["application/json"].get("schema", {}))

            tools.append(
                Tool(
                    name=op_id,
                    description=description or "",
                    parameters=parameters,
                    output=output,
                    triggers=[Trigger(type="manual")],
                    metadata={"method": method.upper(), "path": path},
                )
            )

    return tools
