"""Reuse existing read transport. A build hash change is advisory, not a veto.

Only the original constructor's build-equality gate is relaxed. Current root,
class/field types, getter probes, owner stability and read-only access remain.
No new privileges, broker launch, memory writes, injection or client calls.
"""
import json
from pathlib import Path

def advisory_factory(existing_factory):
    def open_session(pid, *, cancel=None):
        try:
            return existing_factory(pid,cancel=cancel)
        except RuntimeError as exc:
            # This exact error occurs BEFORE native roots/fields are read. Other
            # failures (access denied, PID changed, missing fields) are not retried.
            if str(exc)!='현재 클라이언트 버전의 지도 읽기 규칙이 없습니다.': raise
            from mini_masukja.map_memory import MapMemorySession
            from mini_masukja.quest_memory import Reader,file_sha256
            from mini_masukja.paths import resource_dir
            from mini_masukja.character_context import _class
            class AdvisorySession(MapMemorySession):
                def __init__(self):
                    self.reader=Reader(pid,cancel)
                    try:
                        self.base,self.module=self.reader.module_base()
                        self.plan=json.loads((resource_dir()/'ui-rules/map-memory-layout.json').read_text(encoding='utf-8'))
                        self.character_plan=json.loads((resource_dir()/'ui-rules/character-memory-layout.json').read_text(encoding='utf-8'))
                        keys=json.loads((resource_dir()/'ui-rules/map-key-layout.json').read_text(encoding='utf-8'))
                        # Mixed rule files are a structural bundle error, not a game-version mismatch.
                        if any(keys[k]!=self.plan[k] or self.plan[k]!=self.character_plan[k] for k in ('game_assembly_sha256','metadata_sha256')):
                            raise ValueError('현재 지도 읽기 규칙 파일 구성이 서로 다릅니다.')
                        metadata=Path(self.reader.image).parent/'MabinogiMobile_Data/il2cpp_data/Metadata/global-metadata.dat'
                        self.actual_version=dict(game_assembly_sha256=file_sha256(self.module),metadata_sha256=file_sha256(metadata))
                        self._validated={};self._schemas={};self._names={}
                        for row in self.plan['classes']+keys['classes']:
                            key=(row['name'],row['namespace'])
                            if key in self._schemas:raise ValueError('지도 클래스 선언이 중복됩니다.')
                            self._schemas[key]=row
                        identity=next(r for r in self.character_plan['classes'] if r['name']=='ControlObjectIdentityComponent')
                        self.identity_class=_class(self.reader,self.base,identity)
                        self.identity_shape=self.reader.layout(self.identity_class,identity['fields'])
                    except BaseException:
                        self.reader.close();raise
                def read(self, *, include_map=True):
                    value=super().read(include_map=include_map)
                    value['source_version']=self.actual_version
                    value['version_notice']='게임 버전 변경 안내 · 현재 구조·지도 식별 검증을 유지하고 계속 운용'
                    return value
            return AdvisorySession()
    return open_session
