#!/usr/bin/env python3
import argparse
import importlib.machinery
import json
import os
import sys
import types
from pathlib import Path


def stub(name):
    module = types.ModuleType(name)
    module.__path__ = []
    module.__spec__ = importlib.machinery.ModuleSpec(name, loader=None)
    module.__getattr__ = lambda attr: type(attr, (), {})
    sys.modules[name] = module
    return module


def install_abi_stubs():
    # The cache was built for the ticket's container Python ABI. These modules are
    # unrelated to protected_media but are imported at Horilla startup. Stubbing
    # only optional document/data backends lets the exact target URL/view modules run.
    for name in [
        "numpy", "pandas", "openpyxl", "openpyxl.styles", "openpyxl.utils",
        "openpyxl.worksheet", "openpyxl.worksheet.datavalidation",
        "openpyxl.drawing", "openpyxl.drawing.image", "openpyxl.comments", "xhtml2pdf",
        "xhtml2pdf.pisa", "fitz", "pymupdf", "google.auth.transport.requests",
        "google.oauth2.credentials", "google.oauth2.service_account",
        "google_auth_oauthlib.flow", "googleapiclient.discovery",
        "googleapiclient.http", "tablib", "bidi", "bidi.algorithm",
    ]:
        stub(name)
    pil = stub("PIL")
    image = stub("PIL.Image")
    image.Image = type("Image", (), {})
    image.open = lambda *args, **kwargs: None
    pil.Image = image


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--source", required=True)
    parser.add_argument("--deps", required=True)
    parser.add_argument("--compat", required=True)
    parser.add_argument("--django-compat")
    parser.add_argument("--media-root", required=True)
    parser.add_argument("--port", required=True, type=int)
    parser.add_argument("--role", required=True)
    parser.add_argument("--commit", required=True)
    parser.add_argument("--identity-out", required=True)
    args = parser.parse_args()

    paths = [args.compat, args.source, args.deps]
    if args.django_compat:
        paths.insert(0, args.django_compat)
    sys.path[:0] = paths
    install_abi_stubs()

    os.environ.update({
        "DJANGO_SETTINGS_MODULE": "horilla.settings",
        "DEBUG": "True",
        "ALLOWED_HOSTS": "*",
        "SECRET_KEY": "pruva-variant-local-runtime",
        "DB_ENGINE": "django.db.backends.sqlite3",
        "DB_NAME": str(Path(args.media_root).parent / "runtime.sqlite3"),
    })

    import django
    django.setup()
    from django.conf import settings
    settings.MEDIA_ROOT = args.media_root
    settings.ALLOWED_HOSTS = ["*"]
    settings.DEBUG = True
    settings.SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
    settings.MIDDLEWARE = [m for m in settings.MIDDLEWARE if m != "attendance.middleware.AttendanceMiddleware"]

    import base.urls
    import base.views
    import horilla.urls

    import hashlib
    def digest(path):
        return hashlib.sha256(Path(path).read_bytes()).hexdigest()
    identity = {
        "role": args.role,
        "source_commit": args.commit,
        "django_runtime": django.get_version(),
        "base_views_path": base.views.__file__,
        "base_views_sha256": digest(base.views.__file__),
        "base_urls_path": base.urls.__file__,
        "base_urls_sha256": digest(base.urls.__file__),
        "root_urlconf_path": horilla.urls.__file__,
        "media_root": settings.MEDIA_ROOT,
        "server": "Django WSGI reference server via django.core.servers.basehttp.run",
        "abi_stubs": "optional document/data/image backends only; base.views/base.urls/horilla.urls are exact target files",
    }
    Path(args.identity_out).write_text(json.dumps(identity, indent=2, sort_keys=True) + "\n")
    print(json.dumps(identity, sort_keys=True), flush=True)

    from django.core.servers.basehttp import get_internal_wsgi_application, run
    run("0.0.0.0", args.port, get_internal_wsgi_application(), threading=False)


if __name__ == "__main__":
    main()
