#!/usr/bin/python3
""" Create, modify and remove astblick repos"""

# pylint: disable=invalid-name

# Copyright (C) 2024 Gwyn Ciesla

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import getpass
import configparser
import datetime
import shutil
import requests
from urllib3.exceptions import InsecureRequestWarning
import sqlalchemy
from sqlalchemy.pool import StaticPool

import astblick

CONFIGFILENAME = os.path.join(
    os.path.expanduser("~" + getpass.getuser()), ".astblick.conf"
)

CONFIG = astblick.config_handler(CONFIGFILENAME)

DATABASE = astblick.homesub(str(CONFIG.get("Options", "database")))

# connect to DB with shared connection for all threads.
ENGINE = sqlalchemy.create_engine(
    "sqlite:///" + DATABASE,
    connect_args={"check_same_thread": False},
    poolclass=StaticPool,
)

with ENGINE.connect() as dbconn:
    print("------")
    print("ID | Repository Name | Gitolite URL | RSA key path | Last refresh")
    print("------")
    for repoid, reponame, updated, url, key in dbconn.execute(
        sqlalchemy.select(astblick.TABLE_REPO)
    ).fetchall():
        formdate = datetime.datetime.fromtimestamp(updated).strftime(
            "%I:%M %p, %Y-%m-%d"
        )
        print(
            str(repoid)
            + " | "
            + reponame
            + " | "
            + url
            + " | "
            + key
            + " | "
            + formdate
        )
    print("------\n")

RESPONSE = input("(a)dd, (e)dit, (d)elete, (r)efresh, (q)uit: ")
if RESPONSE == "a":
    nextid = ""
    defaultkey = "~/.ssh/astblick"
    REPONAME = input("Repository Name: ")
    if os.path.exists(
        os.path.join(
            os.path.expanduser("~" + getpass.getuser()), ".astblickrepos/" + REPONAME
        )
    ):
        print("Repo " + REPONAME + " already exists.")
        sys.exit(0)
    URL = input("Git repo URL: ")
    KEY = input("Path to RSA key (" + defaultkey + "): ")
    if KEY != "":
        newkey = KEY
    else:
        newkey = defaultkey
    with ENGINE.connect().execution_options(isolation_level="AUTOCOMMIT") as dbconn:
        for repoid in dbconn.execute(
            sqlalchemy.text("SELECT repoid FROM repo ORDER BY repoid DESC LIMIT 1;")
        ).fetchall():
            nextid = str(int(repoid[0]) + 1)
        if nextid == "":
            nextid = "1"
        dbconn.execute(
            sqlalchemy.insert(astblick.TABLE_REPO).values(
                repoid=nextid, reponame=REPONAME, updated=0, url=URL, key=newkey
            )
        )
    sys.exit(0)

if RESPONSE == "e":
    UPDATE = 0
    REPO = input("Enter repo ID: ")
    with ENGINE.connect() as dbconn:
        for reponame, url, key in dbconn.execute(
            sqlalchemy.select(
                astblick.TABLE_REPO.c.reponame,
                astblick.TABLE_REPO.c.url,
                astblick.TABLE_REPO.c.key,
            ).where(astblick.TABLE_REPO.c.repoid == REPO)
        ).fetchall():  # pylint: disable=line-too-long
            NEWNAME = input("Repository Name (" + reponame + "): ")
            if os.path.exists(
                os.path.join(
                    os.path.expanduser("~" + getpass.getuser()),
                    ".astblickrepos/" + NEWNAME,
                )
            ):
                print("Repo " + NEWNAME + " already exists.")
                sys.exit(0)
            NEWURL = input("Gitolite URL (" + url + "): ")
            NEWKEY = input("Path to RSA key (" + key + "): ")
            if NEWNAME not in [reponame, ""]:
                shutil.move(
                    os.path.join(
                        os.path.expanduser("~" + getpass.getuser()),
                        ".astblickrepos/" + reponame,
                    ),
                    os.path.join(
                        os.path.expanduser("~" + getpass.getuser()),
                        ".astblickrepos/" + NEWNAME,
                    ),
                )
                reponame = NEWNAME
                UPDATE = 1
            if NEWURL not in [url, ""]:
                url = NEWURL
                UPDATE = 1
            if NEWKEY not in [key, ""]:
                key = NEWKEY
                UPDATE = 1
    if UPDATE == 1:
        with ENGINE.connect().execution_options(isolation_level="AUTOCOMMIT") as dbconn:
            dbconn.execute(
                sqlalchemy.update(astblick.TABLE_REPO)
                .where(astblick.TABLE_REPO.c.repoid == REPO)
                .values(reponame=reponame, url=url, key=key)
            )
    sys.exit(0)

if RESPONSE == "d":
    REPO = input("Enter repo ID: ")
    CONFIRM = input("Confirm deletion of " + REPO + " (y/N)")
    if CONFIRM == "y":
        with ENGINE.connect().execution_options(isolation_level="AUTOCOMMIT") as dbconn:
            for reponame in dbconn.execute(
                sqlalchemy.select(astblick.TABLE_REPO.c.reponame).where(
                    astblick.TABLE_REPO.c.repoid == REPO
                )
            ).fetchall():
                TARGET = str(reponame[0])
            dbconn.execute(
                sqlalchemy.delete(astblick.TABLE_REPO).where(
                    astblick.TABLE_REPO.c.repoid == REPO
                )
            )
        if os.path.exists(
            os.path.join(
                os.path.expanduser("~" + getpass.getuser()), ".astblickrepos/" + TARGET
            )
        ):
            shutil.rmtree(
                os.path.join(
                    os.path.expanduser("~" + getpass.getuser()),
                    ".astblickrepos/" + TARGET,
                )
            )
    sys.exit(0)

if RESPONSE == "r":
    requests.urllib3.disable_warnings(InsecureRequestWarning)
    CONFIGFILENAME = os.path.join(
        os.path.expanduser("~" + getpass.getuser()), ".astblick.conf"
    )
    CONFIG = configparser.ConfigParser()
    CONFIG.read(CONFIGFILENAME)
    IPADDR = str(CONFIG.get("Options", "ip"))
    PORT = str(CONFIG.get("Options", "port"))
    URL = "https://" + IPADDR + ":" + PORT + "/"
    try:
        OUTPUT = requests.get(URL + "refresh", verify=False)
    except OSError:
        print("Unable to connect")
        sys.exit(1)

    if OUTPUT.text == "0":
        print("Git repos refreshed.")
    else:
        print("Git repos not refreshed.")

if RESPONSE == "q":
    sys.exit(0)
