# -*- coding: utf-8 -*-

import os

# Third Part Imports

# Basics Imports
import configuration

# Utils
from bravaweb.utils import GetHeader

# Security
import bravaweb.security as Security

# Router
from bravaweb.router import Router

# Environment
from bravaweb.environment import Environment

# Error Tratament
import traceback

# App Boot Time
from datetime import datetime

# App Log
from bravaweb.utils.log import *

boot_time = datetime.now()


async def App(scope, receive, send, hanndler_error=None):
    if scope["type"] == "lifespan":
        while True:
            message = await receive()
            if message["type"] == "lifespan.startup":
                Router.load_routes()
                await send({"type": "lifespan.startup.complete"})
            elif message["type"] == "lifespan.shutdown":
                await send({"type": "lifespan.shutdown.complete"})
                return

    if scope["type"] not in ("http", "websocket"):
        return

    try:
        try:
            Debug(f"Request '{scope.get('method', 'WS')} {scope.get('path', '/')}'")
            headers = GetHeader(scope)
            Debug("Catching Header")
        except Exception as e:
            if not hanndler_error is None:
                hanndler_error(e, scope, None, 'Global Error: Get Header')
            raise e

        try:

            if scope["method"] == "OPTIONS":
                await Security.origin.Options(headers, send)

            elif Security.origin.Static(scope):
                await Security.origin.NotFound(send)

            elif Security.origin.Permitted(headers, scope):

                try:
                    Debug("Load Environment")
                    environment = Environment(headers, scope, receive, send)

                    Debug("Receiving Body")
                    await environment.ReceiveBody()

                    Debug("Start Response")
                    await environment.Response()

                except Exception as e:
                    if not hanndler_error is None:
                        hanndler_error(e, scope, headers, 'Global Error: Environment, Body Response')
                    Error("App Response Content", e)
                    raise e
            else:
                Error("", "Request Origin Not Authorized", False)
                await Security.origin.Forbidden(send)

        except Exception as e:
            if not hanndler_error is None:
                hanndler_error(e, scope, headers, 'Global Error: Unexpected')
            raise e
    except Exception as e:
        # Global fallback if something went wrong outside the normal controller flow
        try:
            # Fallback if environment failed to build or controller failed
            from bravaweb.response.json import Json
            import configuration
            from bravaweb.utils.response_code import ResponseCode
            
            debug = getattr(configuration.api, "debug", False)
            if debug:
                import traceback
                error_details = {
                    "message": str(e) if e else "Internal Server Error",
                    "traceback": traceback.format_exc(),
                    "context": "Global Catch"
                }
                content = Json().Response(error_details, success=False, error="Internal Error")
                _content_type = b'application/json; charset=utf-8'
            else:
                content = "500: Internal Error".encode(configuration.api.encoding)
                _content_type = b'text/html; charset=utf-8'

            _headers = [
                (b'content-type', _content_type),
                (b"Content-Length", str(len(content)).encode(configuration.api.encoding)),
                (b"X-Frame-Options", b"Deny")
            ]

            # Try to add CORS header if environment exists
            if 'environment' in locals() and hasattr(environment, 'origin') and environment.origin:
                 _headers.append((b"Access-Control-Allow-Origin", environment.origin.encode(configuration.api.encoding)))

            await send({
                'type': 'http.response.start',
                'status': ResponseCode.InternalError.code,
                'headers': _headers
            })

            await send({
                'type': 'http.response.body',
                'body': content
            })
        except Exception as secondary_error:
            # Last resort log
            from bravaweb.utils.log import Error
            Error("Fatal error in global exception handler", secondary_error)
            raise e
