#!/usr/bin/env python3

# https://httpd.apache.org/docs/2.4/en/custom-error.html

WEB_ROOT = "/mit/sipb-www/web_scripts"
REPO_ROOT = "/mit/sipb-www/checkout"

import os
from pathlib import Path
import cgi
from subprocess import check_output, STDOUT, CalledProcessError
from urllib.parse import parse_qs
from bs4 import BeautifulSoup

os.chdir(WEB_ROOT)

request_method = os.environ["REQUEST_METHOD"]
if request_method not in ("GET", "POST"):
    print("Status: 405 Method Not Allowed")
    print()
    exit()

def make_content(environ) -> BeautifulSoup:
    """Writes the 404 message depending on whether your certs are active.
    """
    # add editor / form
    uri = environ["REQUEST_URI"]
    if uri[-1] == '/':
        uri = uri[:-1]
    page = uri.split("/")[-1]

    action_url = f"https://{os.environ['SERVER_NAME']}:444/404.py"
    if environ["SERVER_PORT"] == "444":
        html = BeautifulSoup((
            f'''<h1>{page}</h1>'''
            f'''<p>The page <b><font color="#D81B60">{uri}</font></b> doesn't exist (yet)!</p>'''
            f'''<p>Would you like to create it? First make sure you didn't misspell the page title.</p>'''
            f'''<form method="POST" action="{action_url}">'''
            f'''<input type="hidden" name="page" value="{uri}">'''
            f'''<input type="submit" value="Create '{page}'">'''
            f'''</form>'''
        ), "html.parser")
    else:
        html = BeautifulSoup((
            f'''<h1>{page}</h1>'''
            f'''<p>The page <b><font color="#D81B60">{uri}</font></b> doesn't exist! '''
            f'''Make sure you didn't misspell the page title.</p>'''
            f'''<p>If you're a SIPB member and would like to create this page, make sure you '''
            f'''have your <a href="https://web.mit.edu/certificates/test/">certs</a> installed '''
            f'''before clicking "Create".'''
            f'''<form method="POST" action="{action_url}">'''
            f'''<input type="hidden" name="page" value="{uri}">'''
            f'''<input type="submit" value="Create '{page}'">'''
            f'''</form>'''
        ), "html.parser")

    return html    

def generate_html(inner: BeautifulSoup) -> BeautifulSoup:
    """Get the root HTML to render, as a BeautifulSoup

    Args:
        inner: BeautifulSoup to insert into as page content.
    """
    # open home page and clear content
    with open("hugo/index.html", "rb") as f:
        soup = BeautifulSoup(f, "html.parser")
    content = soup.main
    content.string = ""

    # unselect home
    for nav in soup.find_all("nav"):
        del nav.find("li").a["aria-current"]

    # delete edit and view history links
    soup.footer.find("p").decompose()

    # add the _actual_ inner content
    content.append(inner)

    return soup

def is_sipb_member(kerb):
    sipb_members = {kerb.strip() for kerb in check_output([
            "pts","membership",
            "-cell", "athena.mit.edu",
            "-nameorid", "system:gsipb",
        ]).decode().split('\n')[1:]}
    return kerb in sipb_members or f'{kerb}.root' in sipb_members

def new_page(uri, environ):
    assert ".." not in uri, "Don't be sussy"
    title = uri.split("/")[-1]
    path = Path(f"{uri[1:-len(title)]}")
    page = title + ".md"
    full_path = Path(REPO_ROOT) / "content" / path / page
    email = os.environ.get("SSL_CLIENT_S_DN_Email")
    assert email is not None
    kerb = email.split('@')[0]
    email = email.lower()
    name = os.environ.get('SSL_CLIENT_S_DN_CN')
    assert is_sipb_member(kerb), f"{kerb} is not recognized as a SIPB member!"

    body = f"""
+++
title = "{title}"
author = "{name}"
+++

This page uses [Markdown](https://www.markdownguide.org/cheat-sheet/)!

Go ahead and replace all this text with what you'd like for this page.
""".strip()

    # The actual spooky stuff
    os.chdir(REPO_ROOT)
    full_path.parent.mkdir(parents=True, exist_ok=True)
    assert not full_path.exists(), (
        f"File {page!r} already exists at {str(path)!r}! "
        f"Ask the docs team for what's up with that."
    )
    with open(full_path, "w") as f:
        f.write(body)

    # add file to commit
    check_output(["git", "add", full_path], stderr=STDOUT)
    
    # actual commit
    check_output([
        "git",
        "-c", f"user.name='{name}'",
        "-c", f"user.email={email}",
        "commit",
        "-m", f"add {str(path / page)!r}",
    ], stderr=STDOUT)
    
    # push the changes  
    check_output(['git', 'push'], stderr=STDOUT)

try:
    if request_method == "GET":
        inner = make_content(os.environ)
        soup = generate_html(inner)
        print("Content-Type: text/html; charset=utf-8\n")
        print(soup)
    elif request_method == "POST":
        assert os.environ["SERVER_PORT"] == "444", "Use your certs!"
        post = cgi.FieldStorage()
        uri = post["page"].value
        new_page(uri, os.environ)
        redirect_url = f"https://{os.environ['SERVER_NAME']}:444{uri}"
        print("Status: 303 See Other")
        print(f"Location: {redirect_url}\n")
except CalledProcessError as e:
    print("Content-Type: text/plain\n")
    print(e)
    print(e.output.decode())
except Exception as e:
    print(e)
