from __future__ import annotations

import re

from common_logging import get_logger

logger = get_logger(__name__)

_CN_DIGITS = {'零': 0, '〇': 0, '一': 1, '二': 2, '两': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9}
_CN_UNITS = {'十': 10, '百': 100, '千': 1000, '万': 10000}
_CN_NUMBER_RE = re.compile('[零〇一二两三四五六七八九十百千万]+')
_DROP_CHARS_RE = re.compile('[\\s（）()\\[\\]【】《》〈〉<>〔〕第号,，。；;:：_\\-—]+')
_MARKDOWN_LINK_RE = re.compile('^\\[([^\\]]+)\\]\\([^)]+\\)$')
_WHITESPACE_RE = re.compile('\\s+')

def _parse_chinese_number(token: str) -> int:
    if not any(char in _CN_UNITS for char in token):
        return int(''.join(str(_CN_DIGITS.get(char, 0)) for char in token))
    result = 0
    section = 0
    number = 0
    for char in token:
        if char in _CN_DIGITS:
            number = _CN_DIGITS[char]
            continue
        unit = _CN_UNITS.get(char)
        if unit is None:
            continue
        if unit == 10000:
            section = (section + number) * unit
            result += section
            section = 0
        else:
            section += (number or 1) * unit
        number = 0
    return result + section + number

def normalize_legal_doc_number(value: str | None) -> str:
    if not value:
        return ''
    converted = _CN_NUMBER_RE.sub(lambda match: str(_parse_chinese_number(match.group(0))), value)
    return _DROP_CHARS_RE.sub('', converted)

def normalize_relation_title(value: str | None) -> str:
    if not value:
        return ''
    title = value.strip()
    link = _MARKDOWN_LINK_RE.match(title)
    if link:
        title = link.group(1).strip()
    title = title.strip('《》〈〉[]()（） \t\r\n')
    return _WHITESPACE_RE.sub('', title)

def relation_identity_key(doc_id: int | None=None, doc_number: str | None=None, title: str | None=None, source_url: str | None=None) -> str:
    if doc_id:
        return f'id:{doc_id}'
    if source_url:
        return f'url:{source_url.strip()}'
    raw_number = (doc_number or '').strip()
    if raw_number and (not raw_number.startswith(('《', '〈'))):
        normalized_number = normalize_legal_doc_number(raw_number)
        if normalized_number:
            return f'num:{normalized_number}'
    title_value = title or (raw_number if raw_number.startswith(('《', '〈')) else None)
    normalized_title = normalize_relation_title(title_value)
    if normalized_title:
        return f'title:{normalized_title}'
    logger.warning("failed to generate relation identity key", doc_number=doc_number, title=title)
    return ''

def is_same_legal_reference(external_number: str | None, external_title: str | None, internal_doc_number: str | None, internal_title: str | None) -> bool:
    ext_title = normalize_relation_title(external_title)
    int_title = normalize_relation_title(internal_title)
    if ext_title and int_title and (ext_title == int_title):
        return True
    if normalize_relation_title(external_number) and int_title and (normalize_relation_title(external_number) == int_title):
        return True
    ext_number = normalize_legal_doc_number(external_number)
    int_number = normalize_legal_doc_number(internal_doc_number)
    if not ext_number or not int_number:
        return False
    return ext_number == int_number or ext_number in int_number or int_number in ext_number

def clear_duplicate_external_superseded_by(doc, superseder) -> bool:
    if not doc or not superseder:
        return False
    if not (getattr(doc, 'superseded_by_doc_number', None) or getattr(doc, 'superseded_by_title', None) or getattr(doc, 'superseded_by_source_url', None)):
        return False
    if not is_same_legal_reference(getattr(doc, 'superseded_by_doc_number', None), getattr(doc, 'superseded_by_title', None), getattr(superseder, 'doc_number', None), getattr(superseder, 'title', None)):
        return False
    doc.superseded_by_doc_number = None
    doc.superseded_by_title = None
    doc.superseded_by_source_url = None
    return True
