#WEBSITEBUILDERADDONENGINE
import os
import mimetypes
import subprocess
import threading
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse
from PyQt5.QtWidgets import QMessageBox
from pathlib import Path
import sys
ADDON_DIR = Path(__file__).parent

if str(ADDON_DIR) not in sys.path:
    sys.path.insert(0, str(ADDON_DIR))

import download

PHP_CGI = Path(__file__).parent / "php-addon" / "php-cgi.exe"
ConfigFolder = Path(__file__).parent / "php-addon" / "php.zip"
extractor = Path(__file__).parent / "php-addon"
PORT = 8000

server = None
server_thread = None
web_root = None
RequiredLib = Path(__file__).parent / "download.py"
def INIT(api):
    if not RequiredLib.exists():
        QMessageBox.critical(
                api.window,
                "Mini Apache",
                f"Download.py is required!"
            )
        return

    class MiniApache(BaseHTTPRequestHandler):
        def log_message(self, format, *args):
            pass

        def do_GET(self):
            parsed = urlparse(self.path)
            path = parsed.path.strip("/")

            if path == "":
                path = find_index()
                if not path:
                    self.send_error(404, "No index.php or index.html found")
                    return

            file_path = os.path.abspath(os.path.join(web_root, path))

            if not file_path.startswith(os.path.abspath(web_root)):
                self.send_error(403, "Forbidden")
                return

            if not os.path.exists(file_path):
                self.send_error(404, "File not found")
                return

            if file_path.lower().endswith(".php"):
                run_php(self, file_path, parsed.query)
            else:
                send_static(self, file_path)

    def start_server():
        global server, server_thread, web_root

        if server is not None:
            api.log("Mini Apache already running")
            return

        web_root = api.model.filePath(api.tree.rootIndex())

        if not web_root or not os.path.isdir(web_root):
            QMessageBox.critical(api.window, "Mini Apache", "Open a valid folder first.")
            return

        if not os.path.exists(PHP_CGI):
           download.download("https://downloads.php.net/~windows/releases/archives/php-8.5.8-nts-Win32-vs17-x64.zip", ConfigFolder)
           download.unpack(ConfigFolder, extractor)
        try:
            server = ThreadingHTTPServer(("0.0.0.0", PORT), MiniApache)
            server.daemon_threads = True
            server.timeout = 1

            server_thread = threading.Thread(
                target=server.serve_forever,
                kwargs={"poll_interval": 0.2},
                daemon=True
            )
            server_thread.start()

            api.log(f"Mini Apache running on http://localhost:{PORT}")

        except Exception as e:
            server = None
            server_thread = None
            QMessageBox.critical(api.window, "Mini Apache Error", str(e))

    def stop_server():
        global server, server_thread

        if server is None:
            api.log("Mini Apache is not running")
            return

        old_server = server
        server = None
        server_thread = None

        def shutdown_worker():
            try:
                old_server.shutdown()
                old_server.server_close()
                api.log("Mini Apache stopped")
            except Exception as e:
                print("Server stop error:", e)
                api.log("Mini Apache stop error")

        threading.Thread(target=shutdown_worker, daemon=True).start()
        api.log("Mini Apache stopping...")

    api.add_addon_button("Start Mini Apache", start_server)
    api.add_addon_button("Stop Mini Apache", stop_server)


def find_index():
    for name in ["index.php", "index.html", "index.htm"]:
        full = os.path.join(web_root, name)
        if os.path.exists(full):
            return name
    return None


def send_static(handler, file_path):
    mime, _ = mimetypes.guess_type(file_path)
    if mime is None:
        mime = "application/octet-stream"

    handler.send_response(200)
    handler.send_header("Content-Type", mime)
    handler.end_headers()

    with open(file_path, "rb") as f:
        handler.wfile.write(f.read())


def run_php(handler, file_path, query):
    env = os.environ.copy()
    env["GATEWAY_INTERFACE"] = "CGI/1.1"
    env["SERVER_SOFTWARE"] = "WebsiteBuilderMiniApache"
    env["REQUEST_METHOD"] = "GET"
    env["SCRIPT_FILENAME"] = file_path
    env["SCRIPT_NAME"] = "/" + os.path.relpath(file_path, web_root).replace("\\", "/")
    env["QUERY_STRING"] = query
    env["DOCUMENT_ROOT"] = web_root
    env["REDIRECT_STATUS"] = "200"

    result = subprocess.run(
        [PHP_CGI],
        env=env,
        cwd=web_root,
        capture_output=True
    )

    output = result.stdout

    header_end = output.find(b"\r\n\r\n")
    sep_len = 4

    if header_end == -1:
        header_end = output.find(b"\n\n")
        sep_len = 2

    handler.send_response(200)

    if header_end != -1:
        headers = output[:header_end].decode(errors="ignore")
        body = output[header_end + sep_len:]

        content_type_sent = False

        for line in headers.splitlines():
            if ":" in line:
                key, value = line.split(":", 1)
                key = key.strip()
                value = value.strip()

                if key.lower() == "content-type":
                    content_type_sent = True

                handler.send_header(key, value)

        if not content_type_sent:
            handler.send_header("Content-Type", "text/html")

    else:
        body = output
        handler.send_header("Content-Type", "text/html")

    handler.end_headers()
    handler.wfile.write(body)