import re

from iriusrisk_drl_toolkit.models import RelationRule, Activity

RULE_RE = re.compile(
    r"""
    rule\s+"(?P<name>[^"]+)"\s*
    (?P<attrs>.*?)
    when\s
    (?P<when>.*?)
    then\s
    (?P<then>.*?)
    end
    """,
    re.DOTALL | re.VERBOSE,
)

SALIENCE_RE = re.compile(r"\bsalience\s+(-?\d+)\b")
NO_LOOP_RE = re.compile(r"\bno-loop\s+true\b")

RELATION_TYPE_RE = re.compile(r'relationType\s+==\s*"([^"]+)"')
SRC_TYPE_RE = re.compile(
    r'\$src\s*:\s*Component\s*\(.*?type\s+==\s*"([^"]+)"',
    re.DOTALL,
)
DST_TYPE_RE = re.compile(
    r'\$dst\s*:\s*Component\s*\(.*?type\s+==\s*"([^"]+)"',
    re.DOTALL,
)

ACTION_RE = re.compile(
    r"RuleActions\.createActivity\s*\("
    r'\s*"(?P<kind>[^"]+)"\s*,\s*\$dst\s*,\s*"(?P<value>[^"]+)"\s*'
    r"\s*\)\s*;",
    re.DOTALL,
)

PACKAGE_RE = re.compile(r"^\s*package\s+([A-Za-z0-9_.]+)\s*$", re.MULTILINE)


class UnsupportedRuleError(ValueError):
    pass


def parse_relation_rule(
    drl_text: str,
    *,
    origin: str = "custom",
    editable: bool = True,
) -> RelationRule:
    package_match = PACKAGE_RE.search(drl_text)
    package_name = package_match.group(1) if package_match else None

    rule_match = RULE_RE.search(drl_text)
    if not rule_match:
        raise UnsupportedRuleError("Could not find a supported rule block.")

    name = rule_match.group("name")
    attrs = rule_match.group("attrs")
    when_block = rule_match.group("when")
    then_block = rule_match.group("then")

    salience_match = SALIENCE_RE.search(attrs)
    no_loop_match = NO_LOOP_RE.search(attrs)

    relation_type_match = RELATION_TYPE_RE.search(when_block)
    src_type_match = SRC_TYPE_RE.search(when_block)
    dst_type_match = DST_TYPE_RE.search(when_block)
    action_match = ACTION_RE.search(then_block)

    if not all([relation_type_match, src_type_match, dst_type_match, action_match]):
        raise UnsupportedRuleError(
            "Rule does not match the supported relation->activity subset."
        )

    rule = RelationRule(
        name=name,
        source_type=src_type_match.group(1),
        relation_type=relation_type_match.group(1),
        target_type=dst_type_match.group(1),
        activity=Activity(
            kind=action_match.group("kind"),
            value=action_match.group("value"),
        ),
        salience=int(salience_match.group(1)) if salience_match else None,
        no_loop=bool(no_loop_match),
        origin=origin,
        editable=editable,
        module=package_name,
        raw_drl=drl_text,
    )

    return rule
