#!/usr/bin/env python3

import hashlib
import hmac
from functools import cache
import tempfile
from pathlib import Path

from git import Actor, Repo
from sanic import HTTPResponse, Request, Sanic, response

from make_readme import generate_READMEs

app = Sanic(__name__)


@cache
def github_webhook_secret() -> str:
    return Path("github_webhook_secret").resolve().open(encoding="utf-8").read().strip()


@cache
def github_login() -> str:
    return Path("login").resolve().open(encoding="utf-8").read().strip()


@cache
def github_token() -> str:
    return Path("token").resolve().open(encoding="utf-8").read().strip()


@app.route("/github", methods=["GET"])
async def main_route(request: Request) -> HTTPResponse:
    return response.text(
        "You aren't supposed to go on this page using a browser, it's for webhooks push instead."
    )


@app.route("/github", methods=["POST"])
async def on_push(request: Request) -> HTTPResponse:
    header_signature = request.headers.get("X-Hub-Signature")
    if header_signature is None:
        print("no header X-Hub-Signature")
        return response.json({"error": "No X-Hub-Signature"}, 403)

    sha_name, signature = header_signature.split("=")
    if sha_name != "sha1":
        print("signing algo isn't sha1, it's '%s'" % sha_name)
        return response.json({"error": "Signing algorightm is not sha1 ?!"}, 501)

    # HMAC requires the key to be bytes, but data is string
    mac = hmac.new(
        github_webhook_secret().encode(), msg=request.body, digestmod=hashlib.sha1
    )

    if not hmac.compare_digest(str(mac.hexdigest()), str(signature)):
        return response.json({"error": "Bad signature ?!"}, 403)

    data = request.json

    repository = data["repository"]["full_name"]
    branch = data["ref"].split("/", 2)[2]

    print(f"{repository} -> branch '{branch}'")

    with tempfile.TemporaryDirectory() as folder_str:
        folder = Path(folder_str)
        repo = Repo.clone_from(
            f"https://{github_login()}:{github_token()}@github.com/{repository}",
            to_path=folder,
            single_branch=True,
            branch=branch,
        )

        generate_READMEs(folder)

        repo.git.add("README*.md")
        repo.git.add("ALL_README.md")

        diff_empty = len(repo.index.diff("HEAD")) == 0
        if diff_empty:
            print("nothing to do")
            return response.text("nothing to do")

        repo.index.commit(
            "Auto-update READMEs", author=Actor("yunohost-bot", "yunohost@yunohost.org")
        )
        repo.remote().push(quiet=False)

    return response.text("ok")


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8123, debug=True)