import os
import json
import time
import requests
from flask import render_template
from flava_function.contexts import PRODUCT
from common.context import api_function
from config.endpoints import ENDPOINTS


CONTENT_TYPE_JSON = "application/json"
CONTENT_TYPE_HTML = "text/html"
CONTENT_TYPE_TEXT = "text/plain"

# Record the start time when the module is loaded
start_time = time.time()


def handler(request, context):
    path = request.get("path", "")

    if path == "/":
        return handle_root(context)
    if path == "/function_test_ui":
        project_name = context.get_project()
        func_name = os.environ.get("FUNC_NAME", "")
        func_env = os.environ.get("FUNC_ENVIRONMENT", "")

        endpoint = ENDPOINTS.get(func_env)
        if not endpoint:
            return create_response("Invalid environment", 400)

        console_url = (
            f"{endpoint}/{project_name}/function/function/{func_name}/overview"
        )
        return handle_function_test_ui(console_url, func_name)
    if path == "/get_access_token":
        return handle_access_token(context)
    if path.startswith("/test_timeout"):
        return handle_test_timeout(request)
    if path.startswith("/env/"):
        return handle_env_request(path)
    if path.startswith("/send_request"):
        return handle_send_request(request)
    if path.startswith("/secret_manager/"):
        return handle_secret_manager(request, context)
    if path.endswith((".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".ico")):
        return handle_static_file(path, context)
    if path == "/get_elapsed_time":
        return handle_get_elapsed_time()
    if path == "/test":
        return handle_test(request)
    if path.startswith("/"):
        return handle_markdown_file(path, context)

    return create_response("Invalid request", 400)


def create_response(body, status=200, content_type=CONTENT_TYPE_JSON):
    return {
        "body": body,
        "status": status,
        "headers": {"Content-Type": content_type},
    }


def handle_root(context):
    try:
        body = api_function.render_markdown(None, "Home.md")
        return create_response(body, content_type=CONTENT_TYPE_HTML)
    except FileNotFoundError:
        return create_response("File not found", 404)
    except Exception as e:
        context.log(f"Error rendering markdown: {e}")
        return create_response("Internal server error", 500)


def handle_function_test_ui(console_url, func_name):
    return create_response(
        render_template(
            "function_test.html", console_url=console_url, func_name=func_name
        ),
        content_type=CONTENT_TYPE_HTML,
    )


def handle_test_timeout(request):
    try:
        sleep_time = int(request.get("query", {}).get("sleep", 0))
        time.sleep(sleep_time)
        body = json.dumps(
            {"success": True, "message": f"Slept for {sleep_time} seconds"}
        )
        return create_response(body, content_type=CONTENT_TYPE_JSON)
    except Exception as e:
        body = json.dumps({"success": False, "message": str(e)})
        return create_response(body, 500, CONTENT_TYPE_JSON)


def handle_env_request(path):
    key = path.split("/")[-1]
    value = os.environ.get(key, None)
    body = json.dumps({"value": value})
    return create_response(body, content_type=CONTENT_TYPE_JSON)


def handle_send_request(request):
    host = request.get("query", {}).get("host", "")
    if not host:
        return create_response(
            json.dumps({"success": False, "message": "No host URL provided"}), 400
        )

    try:
        response = requests.get(host, timeout=5)
        response.raise_for_status()
        return create_response(
            json.dumps(
                {"success": True, "message": f"Connected to {host} successfully."}
            ),
            content_type=CONTENT_TYPE_JSON,
        )
    except requests.RequestException as e:
        return create_response(json.dumps({"success": False, "message": str(e)}), 500)


def handle_access_token(context):
    try:
        token = context.get_accesstoken(context.get_product_domain(PRODUCT.FUNCTION))
        body = json.dumps({"token": token})
        return create_response(body, content_type=CONTENT_TYPE_JSON)
    except Exception as e:
        context.log(
            f"Internal error during acquiring ServiceAccount's Access Token: {str(e)}"
        )
        body = json.dumps({"error": {"message": "Internal Server Error"}})
        return create_response(body, 500, CONTENT_TYPE_JSON)


def handle_secret_manager(request, context):
    try:
        parts = request.get("path", "").split("/")
        secret_group = parts[2]
        secret = parts[4]
        version = int(request.get("query", {}).get("version", 0))
        secret_value = context.get_secret(secret_group, secret, version)
        body = json.dumps({"secret": secret_value})
        return create_response(body, content_type=CONTENT_TYPE_JSON)
    except Exception as e:
        context.log(f"Internal error during acquiring secret: {str(e)}")
        body = json.dumps({"error": {"message": "Internal Server Error"}})
        return create_response(body, 500, CONTENT_TYPE_JSON)


def handle_static_file(path, context):
    file_path = path.lstrip("/")  # Remove leading slash
    try:
        with open(file_path, "rb") as file:
            file_content = file.read()
        content_type = determine_content_type(file_path)
        return create_response(file_content, content_type=content_type)
    except FileNotFoundError:
        return create_response("File not found", 404)
    except Exception as e:
        context.log(f"Error serving file: {e}")
        return create_response("Internal server error", 500)


def determine_content_type(file_path):
    if file_path.endswith(".js"):
        return "application/javascript"
    if file_path.endswith(".css"):
        return "text/css"
    if file_path.endswith((".png", ".jpg", ".jpeg", ".gif", ".ico")):
        return "image/" + file_path.split(".")[-1]
    return CONTENT_TYPE_TEXT


def handle_markdown_file(path, context):
    file_path = path.lstrip("/")  # Remove leading slash
    if file_path.endswith(".md"):
        try:
            body = api_function.render_markdown(None, file_path)
            return create_response(body, content_type=CONTENT_TYPE_HTML)
        except FileNotFoundError:
            return create_response("File not found", 404)
        except Exception as e:
            context.log(f"Error rendering markdown: {e}")
            return create_response("Internal server error", 500)
    return create_response("Invalid request", 400)


def handle_get_elapsed_time():
    end_time = time.time()
    elapsed_time = end_time - start_time
    body = json.dumps({"value": elapsed_time})
    return create_response(body, content_type=CONTENT_TYPE_JSON)


def handle_test(request):
    return api_function.make_common_response(request=request)
