from django.conf import settings
from django.http import FileResponse, Http404, JsonResponse
from django.middleware.csrf import get_token
from django.views.decorators.http import require_GET


@require_GET
def csrf_token(request):
    """
    Returns a CSRF token for plain HTML/JS frontends.
    Call this once on page load, then include the token
    as X-CSRFToken header on every POST request.
    """
    return JsonResponse({'csrfToken': get_token(request)})


# The exact policy `front/src/renderer/index.web.html` already carries as a
# <meta> tag, repeated here as a response HEADER — the one thing a <meta> CSP
# cannot express, `frame-ancestors`. Keep the two in sync; a change to either
# CSP without the other is exactly the drift docs/pwa-boundary.md §5 warns
# about. `X-Frame-Options: DENY` comes from `XFrameOptionsMiddleware` already
# in MIDDLEWARE, so `frame-ancestors 'none'` here is belt-and-braces for the
# handful of browsers that honour one and not the other.
PWA_CSP = (
    "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; "
    "font-src 'self' data:; img-src 'self' data:; media-src 'self' blob:; "
    "connect-src 'self'; frame-ancestors 'none'"
)


@require_GET
def pwa_index(request):
    """
    `GET /app/` — the PWA's one HTML file.

    Rendered by a view rather than served statically for the one directive a
    `<meta>` CSP cannot express (see `PWA_CSP` above). The client uses
    `HashRouter` (`front/src/renderer/main.web.jsx`), so every route the app
    knows about is a fragment on this one URL — there is no SPA catch-all to
    write here.
    """
    index_path = settings.PWA_DIR / 'index.html'
    if not index_path.exists():
        raise Http404('PWA build not present. Run `npm run build:web` in front/ and commit backend/pwa/.')

    response = FileResponse(open(index_path, 'rb'), content_type='text/html')
    response['Content-Security-Policy'] = PWA_CSP
    return response


@require_GET
def pwa_service_worker(request):
    """
    `GET /app/sw.js` — its own route, for its own SCOPE.

    A service worker served from `/static/app/sw.js` has scope `/static/app/`
    and controls nothing under `/app/`. Served from here it also carries
    `Cache-Control: no-cache`, without which a cached worker is an app that
    cannot be updated.
    """
    sw_path = settings.PWA_DIR / 'sw.js'
    if not sw_path.exists():
        raise Http404('PWA build not present.')

    response = FileResponse(open(sw_path, 'rb'), content_type='text/javascript')
    response['Cache-Control'] = 'no-cache'
    return response