import re

from gitlint.options import ListOption
from gitlint.rules import CommitMessageTitle, LineRule, RuleViolation

RULE_REGEX = re.compile(r"([^(]+?)(\([^)]+?\))?!?: .+")


class ConventionalCommit(LineRule):
    """ This rule enforces the spec at https://www.conventionalcommits.org/. """

    name = "contrib-title-conventional-commits"
    id = "CT1"
    target = CommitMessageTitle

    options_spec = [
        ListOption(
            "types",
            ["fix", "feat", "chore", "docs", "style", "refactor", "perf", "test", "revert", "ci", "build"],
            "Comma separated list of allowed commit types.",
        )
    ]

    def validate(self, line, _commit):
        violations = []
        match = RULE_REGEX.match(line)

        if not match:
            msg = "Title does not follow ConventionalCommits.org format 'type(optional-scope): description'"
            violations.append(RuleViolation(self.id, msg, line))
        else:
            line_commit_type = match.group(1)
            if line_commit_type not in self.options["types"].value:
                opt_str = ', '.join(self.options['types'].value)
                violations.append(RuleViolation(self.id, f"Title does not start with one of {opt_str}", line))

        return violations
