import json
from starlette.responses import HTMLResponse
from fastapi import FastAPI


def get_swagger_ui_html(*,
                        openapi_url: str,
                        title: str,
                        swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js",
                        swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css",
                        swagger_extra_css_url: str | None = None,
                        swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
                        oauth2_redirect_url: str | None = None,
                        init_oauth: dict | None = None,
                        swagger_ui_parameters: dict | None = None,
                       ) -> HTMLResponse:
    from fastapi.encoders import jsonable_encoder
    from fastapi.openapi.docs import swagger_ui_default_parameters
    current_swagger_ui_parameters = swagger_ui_default_parameters.copy()
    if swagger_ui_parameters:
        current_swagger_ui_parameters.update(swagger_ui_parameters)
    html = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <link type="text/css" rel="stylesheet" href="{swagger_css_url}">
            <link rel="shortcut icon" href="{swagger_favicon_url}">
            <title>{title}</title>
        </head>
        <body>
            <div id="swagger-ui"></div>
            <script src="{swagger_js_url}"></script>
            <script>
                const ui = SwaggerUIBundle({{
                    url: '{openapi_url}',
    """
    if swagger_extra_css_url is not None:
        html = html.replace('</head>', f'<link type="text/css" rel="stylesheet" href="{swagger_extra_css_url}"></head>')
    for key, value in current_swagger_ui_parameters.items():
        html += f"{json.dumps(key)}: {json.dumps(jsonable_encoder(value))},\n"
    if oauth2_redirect_url:
        html += f"oauth2RedirectUrl: window.location.origin + '{oauth2_redirect_url}',"
    html += """
        presets: [
            SwaggerUIBundle.presets.apis,
            SwaggerUIBundle.SwaggerUIStandalonePreset
            ],
        })"""
    if init_oauth:
        html += f"ui.initOAuth({json.dumps(jsonable_encoder(init_oauth))})"
    html += """
        </script>
        </body>
        </html>
        """
    return HTMLResponse(html)


def create_docs(app: FastAPI):
    swagger_ui_parameters = {
        "displayOperationId": True,
        "layout": "BaseLayout",
        "showExtensions": True,
        "showCommonExtensions": True,
        "deepLinking": False,
        "dom_id": "#swagger-ui",
    }

    @app.get("/docs", include_in_schema=False) # override for the default fastapi swagger route
    async def custom_swagger_html():
        res = get_swagger_ui_html(
            title=f'{app.title}: Swagger UI',
            openapi_url=app.openapi_url,
            swagger_favicon_url='/file=ui/assets/favicon.svg',
            swagger_css_url='/file=ui/css/swagger.css',
            swagger_ui_parameters=swagger_ui_parameters,
        )
        return res


def create_redocs(app: FastAPI):
    from fastapi.openapi.docs import get_redoc_html
    @app.get("/redocs", include_in_schema=False) # override for the default fastapi redocs route
    async def custom_redoc_html():
        res = get_redoc_html(
            title=f'{app.title}: ReDoc',
            openapi_url=app.openapi_url,
            redoc_favicon_url='/file=ui/assets/favicon.svg',
        )
        return res