import json
import logging
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any


class JsonFormatter(logging.Formatter):
    def format(self, record: logging.LogRecord) -> str:
        payload: dict[str, Any] = {
            "timestamp": datetime.now(timezone.utc).isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
        }
        for key in (
            "method",
            "path",
            "status_code",
            "duration_ms",
            "client_ip",
            "error_code",
            "agency_id",
            "user_id",
            "filename",
            "company_code",
            "extraction_id",
        ):
            if hasattr(record, key):
                payload[key] = getattr(record, key)
        if record.exc_info:
            payload["exception"] = self.formatException(record.exc_info)
        return json.dumps(payload, ensure_ascii=False)


def configure_logging(*, debug: bool, use_json: bool, log_dir: str | None = None) -> None:
    root = logging.getLogger()
    root.handlers.clear()
    root.setLevel(logging.INFO)

    console_handler = logging.StreamHandler(sys.stdout)
    if use_json:
        console_handler.setFormatter(JsonFormatter())
    else:
        console_handler.setFormatter(
            logging.Formatter("%(asctime)s %(levelname)s [%(name)s] %(message)s")
        )
    root.addHandler(console_handler)

    if debug:
        logging.getLogger("app").setLevel(logging.DEBUG)
    else:
        logging.getLogger("app").setLevel(logging.INFO)

    for noisy in (
        "sqlalchemy.engine",
        "sqlalchemy.orm",
        "sqlalchemy.pool",
        "urllib3",
        "watchfiles",
        "multipart",
        "asyncio",
        "apscheduler",
    ):
        logging.getLogger(noisy).setLevel(logging.WARNING)

    logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
    logging.getLogger("uvicorn.error").setLevel(logging.INFO)

    if log_dir:
        log_path = Path(log_dir)
        log_path.mkdir(parents=True, exist_ok=True)
        error_file = log_path / "errors.log"
        file_handler = logging.FileHandler(error_file, encoding="utf-8")
        file_handler.setLevel(logging.ERROR)
        file_handler.setFormatter(JsonFormatter())
        root.addHandler(file_handler)


def log_extra(**kwargs: Any) -> dict[str, Any]:
    """Build structured `extra` fields for logger calls."""
    return kwargs
