""" commit-msg hook for git.

Hook checks and alters commit message content based
on given rules.

Commits themselves should use convention::

    '<prefix>1234: Commit message'

To use branch as basis for commit message creation. Then they should start with::

    <prefix>1234

This means that following branch names are okay::

    <prefix>1234
    <prefix>1234_human_readable
    <prefix>1234.human.readable
    <prefix>1234HUMANREADABLE

as long next char after ticket number is not digit, its okay.
"""
import sys
import typing
import argparse

from collections import namedtuple

from add_ticket_hook.utils import parse_prefixes, parse_ticket, is_special_commit, valid_commit_message, alter_message
from add_ticket_hook import io


Options = namedtuple("Options", "prefixes,noticket")

DEFAULT_PROJECT_PREFIX = ["CMP-"]
NOTICKET_SENTINEL = "NOJIRA"

SAMPLE_FORMAT = f"'{DEFAULT_PROJECT_PREFIX}999 some additional text here'"


def parse_args(argv: typing.Optional[typing.Sequence[str]] = None) -> typing.Tuple[str, Options]:
    parser = argparse.ArgumentParser()
    parser.add_argument("filenames", nargs="*", help="Commit filename")
    parser.add_argument(
        "-p",
        "--prefixes",
        action="append",
        default=DEFAULT_PROJECT_PREFIX,
        help="Possible ticket prefixes. Comma separated list.",
    )

    args = parser.parse_args(argv)

    assert args.filenames, "No commit filename given"
    assert args.prefixes, "No prefixes specified in config"

    prefixes = parse_prefixes(args.prefixes)

    return args.filenames[0], Options(prefixes=prefixes, noticket=NOTICKET_SENTINEL)


def main_prepare_commit_message() -> int:
    filename, options = parse_args(sys.argv[1:])
    branch_name = io.get_current_branch_name()
    commit_message = io.read_commit_message(filename)
    if not is_special_commit(commit_message):
        commit_message = alter_message(commit_message, branch_name, options.prefixes, noticket_sentinel=options.noticket)
        io.write_commit_message(filename, commit_message)
    return 0


def main_check_commit_message() -> int:
    filename, options = parse_args(sys.argv[1:])
    commit_message = io.read_commit_message(filename)

    ticket_from_commit = parse_ticket(commit_message, options.prefixes)

    if is_special_commit(commit_message):
        return 0
    elif ticket_from_commit:
        if valid_commit_message(ticket_from_commit, commit_message):
            return 0
        else:
            print(
                "ERROR: Ticket was found in the commit message but not at the right place, "
                "it is expected that the message starts with the ticket number "
                f"as in {SAMPLE_FORMAT}"
            )
            return 1
    else:
        print(
            "ERROR: No ticket was found in the commit message, "
            "It is expected that the message starts with the ticket number "
            f"as in {SAMPLE_FORMAT}"
        )
        return 1


if __name__ == "__main__":
    exit(main_prepare_commit_message())
