import sys
import json
import os
import re

from app.main import app

def slugify(text):
    return re.sub(r'[^a-zA-Z0-9]+', '-', text.lower()).strip('-')

def generate_docs(openapi_schema):
    paths = openapi_schema.get("paths", {})
    components = openapi_schema.get("components", {}).get("schemas", {})
    
    groups = {}
    
    for path, methods in paths.items():
        for method, spec in methods.items():
            tags = spec.get("tags", [])
            if tags and tags[0]:
                group_name = tags[0]
            else:
                segments = [s for s in path.split('/') if s]
                if segments:
                    group_name = segments[0].capitalize()
                else:
                    group_name = "General"
                    
            if group_name not in groups:
                groups[group_name] = []
            
            groups[group_name].append((path, method, spec))
            
    # Always write to project's doc directory
    # If run from /app/.agent/utils, we need to go up to /app/ai-hub/docs
    # Let's use absolute route or assume we are executed from inside /app/ai-hub
    script_dir = os.path.dirname(os.path.abspath(__file__))
    docs_dir = os.path.abspath(os.path.join(script_dir, "../../ai-hub/docs/api_reference"))
    os.makedirs(docs_dir, exist_ok=True)
    
    index_md = "# API Reference\n\nThis API reference is grouped by feature:\n\n"
    
    for group_name, endpoints in groups.items():
        file_name = f"{slugify(group_name)}.md"
        index_md += f"- [{group_name}](./{file_name})\n"
        
        md = f"# API Reference: {group_name}\n\n"
        
        for path, method, spec in endpoints:
            md += f"## {method.upper()} `{path}`\n\n"
            summary = spec.get('summary', 'No summary provided.')
            description = spec.get('description', summary)
            
            md += f"**Summary:** {summary}\n\n"
            md += f"**Description:** {description}\n\n"
            
            parameters = spec.get("parameters", [])
            has_user_id = False
            query_params = []
            if parameters:
                md += "#### Parameters\n\n"
                md += "| Name | In | Required | Type | Description |\n"
                md += "|------|----|----------|------|-------------|\n"
                for param in parameters:
                    name = param.get("name", "")
                    in_ = param.get("in", "")
                    if in_.lower() == "header" and name.lower() == "x-user-id":
                        has_user_id = True
                    if in_.lower() == "query":
                        query_params.append(f"{name}=<{name}>")
                        
                    required = "Yes" if param.get("required") else "No"
                    schema = param.get("schema", {})
                    p_type = schema.get("type", "any")
                    if "anyOf" in schema:
                        p_type = "anyOf"
                    desc = param.get("description", "").replace('\n', ' ')
                    md += f"| `{name}` | {in_} | {required} | {p_type} | {desc} |\n"
                md += "\n"
            
            requestBody = spec.get("requestBody", {})
            is_multipart = False
            
            if requestBody:
                md += "#### Request Body\n\n"
                required = "Yes" if requestBody.get("required") else "No"
                md += f"**Required:** {required}\n\n"
                if "description" in requestBody:
                    md += f"{requestBody['description']}\n\n"
                content = requestBody.get("content", {})
                for media_type, media_schema in content.items():
                    md += f"- **Media Type:** `{media_type}`\n"
                    if "multipart/form-data" in media_type:
                        is_multipart = True
                    schema_ref = media_schema.get("schema", {})
                    if "$ref" in schema_ref:
                        ref_name = schema_ref["$ref"].split("/")[-1]
                        md += f"- **Schema:** `{ref_name}` (Define in Models)\n"
                md += "\n"
                    
            responses = spec.get("responses", {})
            if responses:
                md += "#### Responses\n\n"
                md += "| Status Code | Description |\n"
                md += "|-------------|-------------|\n"
                for status_code, response_spec in responses.items():
                    desc = response_spec.get('description', '')
                    md += f"| `{status_code}` | {desc} |\n"
                md += "\n"
                
            md += "#### Example Usage\n\n"
            md += "```bash\n"
            
            full_path = f"http://localhost:8000/api/v1{path}"
            if query_params:
                full_path += "?" + "&".join(query_params)
                
            md += f"curl -X '{method.upper()}' \\\n"
            md += f"  '{full_path}' \\\n"
            md += f"  -H 'accept: application/json'"
            
            if has_user_id:
                md += " \\\n  -H 'X-User-ID: <your_user_id>'"
                
            if requestBody and not is_multipart:
                md += " \\\n  -H 'Content-Type: application/json' \\\n"
                md += f"  -d '{{}}'"
            elif is_multipart:
                md += " \\\n  -H 'Content-Type: multipart/form-data' \\\n"
                md += "  -F 'file=@/path/to/file'"
                
            md += "\n```\n\n"
            md += "---\n\n"
            
        with open(os.path.join(docs_dir, file_name), "w") as f:
            f.write(md)
            
    if components:
        md = "# Models (Schemas)\n\n"
        for name, schema in components.items():
            md += f"## `{name}`\n\n"
            md += f"**Type:** `{schema.get('type', 'object')}`\n\n"
            if "description" in schema:
                md += f"**Description:** {schema['description']}\n\n"
            
            properties = schema.get("properties", {})
            if properties:
                md += "| Property | Type | Description |\n"
                md += "|----------|------|-------------|\n"
                required_fields = schema.get("required", [])
                for prop_name, prop_spec in properties.items():
                    p_type = prop_spec.get("type", "")
                    if "$ref" in prop_spec:
                        p_type = "Ref: " + prop_spec["$ref"].split("/")[-1]
                    if "anyOf" in prop_spec:
                        p_type = "anyOf"
                    req = "*" if prop_name in required_fields else ""
                    desc = prop_spec.get("description", "").replace('\n', ' ')
                    md += f"| `{prop_name}{req}` | `{p_type}` | {desc} |\n"
                md += "\n"
        
        with open(os.path.join(docs_dir, "models.md"), "w") as f:
            f.write(md)
            
        index_md += "- [Models (Schemas)](./models.md)\n"
            
    with open(os.path.join(docs_dir, "index.md"), "w") as f:
        f.write(index_md)
        
    print(f"Documentation generated successfully at {docs_dir}!")

if __name__ == "__main__":
    # execute with python3 from within /app/ai-hub
    schema = app.openapi()
    generate_docs(schema)
