#!/usr/bin/env python3
"""
Commit message checking.
"""
import sys
from typing import List, Optional

__author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"

SHORT_MESSAGE_MAX_LENGTH: int = 50
MESSAGE_MAX_LENGTH: int = 72


def check_file(file_name: str) -> Optional[str]:
    """
    Exit program with exit code 1 if commit message does not conform the rules.

    :param file_name: commit message file name
    """
    with open(file_name, encoding="utf-8") as input_file:
        parts: List[str] = list(map(lambda x: x[:-1], input_file.readlines()))
    return check_commit_message(parts)


def check_commit_message(parts: List[str]) -> Optional[str]:
    """Check whether the commit message is well-formed."""
    short_message: str = parts[0]

    if short_message[0] != short_message[0].upper():
        return (
            short_message
            + "\n^"
            + "\nCommit message short description should start with uppercase "
            + "letter."
        )

    if len(short_message) > SHORT_MESSAGE_MAX_LENGTH:
        return (
            short_message
            + "\n"
            + " " * SHORT_MESSAGE_MAX_LENGTH
            + "^" * (len(short_message) - SHORT_MESSAGE_MAX_LENGTH)
            + "\nCommit message short description should not be longer than "
            + f"{SHORT_MESSAGE_MAX_LENGTH} symbols."
        )

    if len(parts) > 1:
        if parts[1]:
            return (
                "Commit message should have new line after short description."
            )
        for part in parts[2:]:
            if len(part.strip()) > 0 and part.strip()[0] == "#":
                continue
            if len(part) > MESSAGE_MAX_LENGTH:
                return (
                    part
                    + "\n"
                    + " " * MESSAGE_MAX_LENGTH
                    + "^" * (len(part) - MESSAGE_MAX_LENGTH)
                    + "\nCommit message description should not be longer than "
                    + f"{MESSAGE_MAX_LENGTH} symbols."
                )

    if not short_message.endswith("."):
        return (
            short_message
            + "\n"
            + " " * (len(short_message) - 1)
            + "^"
            + '\nCommit message should end with ".".'
        )

    def first_letter_uppercase(text: str):
        """Change first letter to upper case."""
        return text[0].upper() + text[1:]

    verbs_1 = ["add", "fix", "check", "refactor"]
    verbs_2 = [
        "change",
        "remove",
        "create",
        "update",
        "rename",
        "move",
        "swap",
        "treat",
        "suppress",
    ]

    verbs = {"got": "get"}
    for verb in verbs_1:
        verbs[verb + "ed"] = verb
    for verb in verbs_2:
        verbs[verb + "d"] = verb

    for wrong_verb, right_verb in verbs.items():
        if short_message.startswith(
            f"{wrong_verb} "
        ) or short_message.startswith(f"{first_letter_uppercase(wrong_verb)} "):
            return (
                f"Commit message should start with the verb in infinitive "
                f"form. Please, use "
                f'"{first_letter_uppercase(right_verb)} ..." instead of '
                f'"{first_letter_uppercase(wrong_verb)} ...".'
            )


def check(commit_message: str) -> None:
    """Print commit_message and checking result."""
    print("\033[33m" + commit_message + "\033[0m")
    print(check_commit_message(commit_message.split("\n")))


def test():
    """Test rules."""
    check("start with lowercase letter.")
    check("Added foo.")
    check("Created foo.")
    check("Doesn't end with dot")
    check("To-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o long")


if __name__ == "__main__":
    if sys.argv[1] == "__test__":
        test()
    else:
        print("Checking commit message...")
        message = check_file(sys.argv[1])
        if message is not None:
            print(message)
            sys.exit(1)