"""Perl source parser (regex-based)."""

from __future__ import annotations

import re

from codectx.parser.types import DependencyRecord, EntityRecord, ParseResult

_PACKAGE_RE = re.compile(r"^\s*package\s+([\w:]+)\s*;", re.MULTILINE)
_USE_RE     = re.compile(r"^\s*use\s+([\w:]+)(?:\s+[\d.]+)?(?:\s+.*)?\s*;", re.MULTILINE)
_REQUIRE_RE = re.compile(r"""^\s*require\s+(?:'([^']+)'|"([^"]+)"|([\w:]+))\s*;""", re.MULTILINE)
_SUB_RE     = re.compile(r"^(\s*)sub\s+(\w+)\s*\{", re.MULTILINE)
_OUR_RE     = re.compile(r"^\s*our\s+(?:@|%|\$)(\w+)\s*=", re.MULTILINE)
_MY_VAR_RE  = re.compile(r"^\s*my\s+(?:@|%|\$)(\w+)\s*=\s*sub\s*\{", re.MULTILINE)

_BUILTIN_USE  = {"strict", "warnings", "utf8", "feature", "Exporter", "base", "parent", "POSIX", "Carp", "Scalar::Util", "List::Util"}


def _ln(content: str, pos: int) -> int:
    return content[:pos].count("\n") + 1


def parse_perl(file_path: str, content: str) -> ParseResult:
    result = ParseResult(file_path=file_path, language="perl")

    for m in _PACKAGE_RE.finditer(content):
        result.entities.append(EntityRecord(
            name=m.group(1), qualified_name=m.group(1), type="package",
            start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
            language="perl",
        ))

    for m in _USE_RE.finditer(content):
        pkg = m.group(1)
        is_local = pkg not in _BUILTIN_USE and not pkg.startswith(("POSIX", "Carp", "strict", "warnings"))
        result.dependencies.append(DependencyRecord(
            path=pkg, type="use", line_number=_ln(content, m.start()), is_local=is_local,
        ))

    for m in _REQUIRE_RE.finditer(content):
        path = m.group(1) or m.group(2) or m.group(3) or ""
        result.dependencies.append(DependencyRecord(
            path=path, type="require", line_number=_ln(content, m.start()), is_local=True,
        ))

    for m in _SUB_RE.finditer(content):
        name = m.group(2)
        result.entities.append(EntityRecord(
            name=name, qualified_name=name, type="function",
            start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
            language="perl",
        ))

    for m in _MY_VAR_RE.finditer(content):
        result.entities.append(EntityRecord(
            name=m.group(1), qualified_name=m.group(1), type="function",
            start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
            language="perl",
        ))

    return result
