"""Bounded, credential-free diagnostics shared by adapters and policy management."""

MESSAGES = {
    'CONTRACT_MODE_MISMATCH': '선택 모드와 요청 형식이 다릅니다.',
    'INVALID_SNAPSHOT': '채널 전체 설정과 필수 목록을 확인하세요.',
    'INVALID_ROI': 'ROI ID 또는 좌표 형식이 잘못되었습니다.',
    'DUPLICATE_ROI_ID': '같은 요청에 ROI ID가 중복되었습니다.',
    'DUPLICATE_RULE_ID': '같은 채널 요청에 규칙 ID가 중복되었습니다.',
    'ROI_REFERENCE_NOT_FOUND': '규칙이 참조한 ROI가 없습니다.',
    'EMPTY_EFFECTIVE_REGION': '전체 화면의 외부는 빈 영역입니다. 규칙을 끄거나 영역을 수정하세요.',
    'FULL_FRAME_ID_CONFLICT': '전체 화면 예약 ID와 일반 영역이 충돌합니다.',
    'INVALID_RULE_CONFIG': '규칙의 필수값 또는 매개변수가 잘못되었습니다.',
    'ROI_LIMIT_EXCEEDED': '채널의 ROI 개수가 허용 상한을 초과합니다.',
    'RULE_LIMIT_EXCEEDED': '채널의 규칙 개수가 허용 상한을 초과합니다.',
    'POLICY_LIMIT_CONFLICT': '적용된 채널 설정과 충돌합니다. 채널 설정을 먼저 줄이세요.',
    'POLICY_ID_CONFLICT': '적용된 일반 ROI와 예약 ID가 충돌합니다.',
    'POLICY_REVISION_CONFLICT': '설정이 변경되었습니다. 상태를 다시 조회하세요.',
    'INVALID_POLICY': '관리 설정의 형식 또는 값이 잘못되었습니다.',
    'POLICY_PERSISTENCE_FAILED': '설정 저장에 실패했습니다. 실제 적용 상태를 다시 확인하세요.',
    'POLICY_NOT_CONFIGURED': '저장소 밖 관리 설정 경로가 준비되지 않았습니다.',
    'POLICY_AUTH_REQUIRED': '관리 인증이 필요합니다.',
    'MULTI_ROI_SETTINGS_OWNED': '다중 ROI 설정은 전체 Start snapshot으로 변경하세요.',
    'START_FAILED': '새 분석 기동에 실패했습니다. 현재 채널 상태를 확인하세요.',
    'CAMERA_COMMAND_BUSY': '해당 채널의 명령을 처리 중입니다. 결과 확인 후 다시 요청하세요.',
}


class RoiError(ValueError):
    def __init__(self, code, *, field=None, camera=None, roi=None, rule=None,
                 actual=None, limit=None, retained=True):
        if code not in MESSAGES:
            raise ValueError('Unknown multi ROI error code.')
        super().__init__(code)
        self.code, self.retained = code, retained
        # Never include raw request values, exceptions or paths supplied by a client.
        self.details = {k: v for k, v in dict(field=field, cameraId=camera,
                        roiId=roi, ruleId=rule, actual=actual, limit=limit).items()
                        if v is not None}

    def payload(self, request_id=None):
        return dict(error=self.code, message=MESSAGES[self.code],
                    details=dict(self.details), requestId=request_id,
                    existingRunPreserved=self.retained,
                    nextAction='설정을 확인한 뒤 채널 전체 설정을 다시 보내세요.')
