#!/usr/bin/python3
import sys
import os
import glob
import subprocess
import fcntl
import contextlib
import syslog

from mini_buildd import cli


#: Needed for man page hack in setup.py
DESCRIPTION = "Script to use as a 'command' in an authorized_key file to allow authorization to mini-buildd uploads via SSH"
EPILOG = """
See ``mini-buildd-ssh-setup --help`` for further explanations.
"""

# Use syslog, facility user, to log access and key
syslog.openlog(facility=syslog.LOG_USER)


def log(msg):
    print(msg, file=sys.stderr)
    syslog.syslog(syslog.LOG_NOTICE, msg)


@contextlib.contextmanager
def filelock(lockfile_path):
    with open(lockfile_path, "w", encoding="UTF-8") as lockfile:
        fcntl.lockf(lockfile, fcntl.LOCK_EX)
        yield
        fcntl.lockf(lockfile, fcntl.LOCK_UN)


class CLI(cli.CLI):
    ALLOWED_COMMAND = "/usr/lib/openssh/sftp-server"

    def __init__(self):
        super().__init__("mini-buildd-ssh-uploader-command", DESCRIPTION, epilog=EPILOG)
        self.incoming = os.path.expanduser("~") + "/incoming/"
        self.lockfile = os.path.expanduser("~") + "/lock"

    def _clear(self):
        for f in os.scandir(self.incoming):
            if f.is_file():
                os.remove(f)

    def _gpg_key_id(self):
        return subprocess.check_output("gpg --list-secret-keys --with-colons | grep --max-count=1 '^sec' | cut -d: -f5", shell=True).strip().decode(encoding="UTF-8")

    def _runcli(self):
        try:
            original_command = os.environ.get("SSH_ORIGINAL_COMMAND")
            if original_command != self.ALLOWED_COMMAND:
                raise Exception("Only sftp allowed here")  # pylint: disable=broad-exception-raised
            subprocess.check_call([self.ALLOWED_COMMAND])
            changes = glob.glob(self.incoming + "/*.changes")[0]
            subprocess.check_output(["debsign", "--re-sign", "-k", self._gpg_key_id(), changes], stderr=subprocess.STDOUT)
            subprocess.check_output(["dput", cli.DputCf().first_target(), changes], stderr=subprocess.STDOUT)
            log(f"{changes} uploaded from {os.environ.get('SSH_CONNECTION')}")
        except Exception as e:
            log(f"Upload error: {e}")
            if isinstance(e, subprocess.CalledProcessError):
                for line in e.output.split(b"\n"):
                    log(line.decode(encoding="UTF-8"))
        finally:
            self._clear()

    def runcli(self):
        with filelock(self.lockfile):
            self._runcli()


if __name__ == "__main__":
    CLI().run()
