"""
Structured JSON logger with PII redaction support.
"""

from __future__ import annotations

import json
import re
import sys
from datetime import datetime, timezone
from typing import Any

from dvgateway.types import Logger

_PII_PATTERNS: list[tuple[re.Pattern[str], str]] = [
    # Korean mobile numbers: 010-1234-5678 or 01012345678
    (re.compile(r"\b(010|011|016|017|018|019)[-.]?\d{3,4}[-.]?\d{4}\b"), "***-****"),
    # General phone numbers: +82-10-1234-5678
    (re.compile(r"\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,9}"), "[PHONE]"),
]

_REDACTED_FIELDS = {"caller", "callee", "transcript", "text", "password", "secret", "token"}


def _redact_pii(value: Any) -> Any:
    if isinstance(value, str):
        result = value
        for pattern, replacement in _PII_PATTERNS:
            result = pattern.sub(replacement, result)
        return result
    if isinstance(value, dict):
        redacted: dict[str, Any] = {}
        for k, v in value.items():
            if k in _REDACTED_FIELDS:
                redacted[k] = "[REDACTED]"
            else:
                redacted[k] = _redact_pii(v)
        return redacted
    return value


_LEVEL_VALUES = {"debug": 10, "info": 20, "warn": 30, "error": 40}


class _StructuredLogger:
    """Structured JSON logger implementing the Logger protocol."""

    def __init__(
        self,
        level: str = "info",
        redact_pii: bool = True,
        base_context: dict[str, Any] | None = None,
    ) -> None:
        self._min_level = _LEVEL_VALUES.get(level, 20)
        self._should_redact = redact_pii
        self._base_context = base_context or {}

    def _write(self, level: str, ctx: dict[str, Any], msg: str) -> None:
        if _LEVEL_VALUES.get(level, 0) < self._min_level:
            return

        entry: dict[str, Any] = {
            "level": level,
            "time": datetime.now(timezone.utc).isoformat(),
            "msg": msg,
            **self._base_context,
            **((_redact_pii(ctx) if self._should_redact else ctx) or {}),
        }

        line = json.dumps(entry, default=str)
        if level in ("error", "warn"):
            sys.stderr.write(line + "\n")
        else:
            sys.stdout.write(line + "\n")

    def debug(self, ctx: dict[str, Any], msg: str) -> None:
        self._write("debug", ctx, msg)

    def info(self, ctx: dict[str, Any], msg: str) -> None:
        self._write("info", ctx, msg)

    def warn(self, ctx: dict[str, Any], msg: str) -> None:
        self._write("warn", ctx, msg)

    def error(self, ctx: dict[str, Any], msg: str) -> None:
        self._write("error", ctx, msg)


def create_logger(
    level: str = "info",
    redact_pii: bool = True,
    base_context: dict[str, Any] | None = None,
) -> Logger:
    """Create a new structured JSON logger."""
    return _StructuredLogger(level=level, redact_pii=redact_pii, base_context=base_context)  # type: ignore[return-value]


default_logger: Logger = create_logger(level="info", redact_pii=True)
