# -*- coding: utf-8 -*-
import re
import whatap.agent.conf.configure as conf

_PROCGROUP_PREFIX = 'procgroup_'

_rule_cache_signature = None
_compiled_rules = None

_pid_result_cache = {}


def _build_rules(config_dict):
    rules = []
    for key, value in config_dict.items():
        if not key.startswith(_PROCGROUP_PREFIX):
            continue
        group_id = key[len(_PROCGROUP_PREFIX):]
        if not group_id:
            continue
        parts = value.split('@@', 3) if value else []
        group_name = parts[0].strip() if len(parts) > 0 else ''
        if not group_name:
            continue
        user_pat = parts[1].strip() if len(parts) > 1 else ''
        cmd2_pat = parts[2].strip() if len(parts) > 2 else ''
        except_pat = parts[3].strip() if len(parts) > 3 else ''
        # user는 고정 텍스트(plain string)로 처리한다. 정규표현식 컴파일하지 않는다.
        # cmd2/except는 기존대로 정규표현식 유지.
        try:
            cmd2_re = re.compile(cmd2_pat) if cmd2_pat else None
            except_re = re.compile(except_pat) if except_pat else None
        except re.error:
            continue
        rules.append((group_name, user_pat, cmd2_re, except_re))
    return rules


def _get_rules():
    global _rule_cache_signature, _compiled_rules
    config_dict = conf.GetConfig().searchKey(_PROCGROUP_PREFIX)
    current_signature = tuple(sorted(config_dict.items()))
    if current_signature != _rule_cache_signature:
        _rule_cache_signature = current_signature
        _compiled_rules = _build_rules(config_dict)
        _pid_result_cache.clear()
    return _compiled_rules


def find_custom_group(pid, user, cmd2):
    rules = _get_rules()
    if not rules:
        return None

    cache_key = (pid, user or '', cmd2 or '')
    if cache_key in _pid_result_cache:
        return _pid_result_cache[cache_key]

    result = None
    u = user or ''
    c = cmd2 or ''
    for group_name, user_str, cmd2_re, except_re in rules:
        # user는 고정 텍스트 정확 매칭. ''(빈 값)이면 모든 user 허용(와일드카드).
        if user_str and user_str != u:
            continue
        if cmd2_re and not cmd2_re.search(c):
            continue
        if except_re and except_re.search(c):
            continue
        result = group_name
        break

    _pid_result_cache[cache_key] = result
    return result


def list_custom_rules():
    """정의된 커스텀 룰을 (group_name, user) 목록으로 반환한다.
    매칭 프로세스가 없어도 정의된 룰을 placeholder로 emit하기 위해 사용한다.
    설정이 바뀌면 _get_rules()가 룰 캐시를 최신으로 유지한다."""
    rules = _get_rules() or []
    return [(group_name, user_str) for group_name, user_str, _cmd2_re, _except_re in rules]


def gc_pid_cache(live_pids):
    dead = [k for k in _pid_result_cache if k[0] not in live_pids]
    for k in dead:
        del _pid_result_cache[k]
