"""リンクベースパーサー共通ユーティリティ。

ラベルロール URI 定数と href → concept 名抽出ロジックを提供する。
"""

from __future__ import annotations

import re

# ============================================================
# Label role URI constants
# ============================================================

ROLE_LABEL = "http://www.xbrl.org/2003/role/label"
"""Standard label."""

ROLE_TOTAL_LABEL = "http://www.xbrl.org/2003/role/totalLabel"
"""Total label."""

ROLE_VERBOSE_LABEL = "http://www.xbrl.org/2003/role/verboseLabel"
"""Verbose label."""

ROLE_TERSE_LABEL = "http://www.xbrl.org/2003/role/terseLabel"
"""Terse label."""

ROLE_PERIOD_START_LABEL = "http://www.xbrl.org/2003/role/periodStartLabel"
"""Period start label."""

ROLE_PERIOD_END_LABEL = "http://www.xbrl.org/2003/role/periodEndLabel"
"""Period end label."""

ROLE_NEGATED_LABEL = "http://www.xbrl.org/2003/role/negatedLabel"
"""Negated label."""

# ============================================================
# href → concept name extraction
# ============================================================

_XSD_PREFIX_RE = re.compile(r"^(.+)_\d{4}-\d{2}-\d{2}\.xsd$")
"""Standard taxonomy XSD filename pattern (greedy match)."""


def extract_concept_from_href(href: str) -> str | None:
    """xlink:href のフラグメントから concept ローカル名を抽出する。

    Strategy 1（XSD ファイル名ベース）のみを使用し、フォールバックとして
    フラグメント全体を返す。EDINET 固有の Strategy 2（``_[A-Z]`` 後方スキャン）
    は上位パッケージ側に残す。

    Args:
        href: xlink:href 属性値。

    Returns:
        concept ローカル名。フラグメントが見つからない場合は ``None``。
    """
    if "#" not in href:
        return None
    path_part, fragment = href.rsplit("#", 1)
    if not fragment:
        return None
    basename = path_part.rsplit("/", 1)[-1]

    # Strategy 1: standard taxonomy {prefix}_{YYYY-MM-DD}.xsd
    m = _XSD_PREFIX_RE.match(basename)
    if m is not None:
        prefix = m.group(1)
        expected = prefix + "_"
        if fragment.startswith(expected):
            return fragment[len(expected):]

    # Fallback: return fragment as-is
    return fragment
