from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime

from ..core.logger import AppLogger
from ..database.orm import OperationLogORM, UserORM
from ..repositories import OperationLogRepository

logger = AppLogger.get_logger(__name__)


@dataclass(frozen=True)
class OperationLogPage:
    """操作日志分页结果，供 API schema 统一转换。"""

    items: list[OperationLogORM]
    total: int
    page: int
    page_size: int


class OperationLogService:
    """操作日志应用服务：记录关键操作并提供分页查询。"""

    def __init__(self, repository: OperationLogRepository):
        self.repository = repository

    def record(
        self,
        *,
        actor: UserORM | None,
        module: str,
        action: str,
        status: str,
        target_type: str = "",
        target_id: str = "",
        detail: str = "",
        ip_address: str = "",
        user_agent: str = "",
    ) -> OperationLogORM | None:
        """写入操作日志；失败只进错误日志，不阻断原业务请求。"""
        try:
            log = self.repository.create_log(
                user_id=actor.id if actor else None,
                username=_clip(actor.username if actor else "", 64),
                role=_clip(actor.role if actor else "", 32),
                module=_clip(module, 64),
                action=_clip(action, 128),
                target_type=_clip(target_type, 64),
                target_id=_clip(target_id, 128),
                status=_clip(status, 32),
                detail=_clip(detail, 4000),
                ip_address=_clip(ip_address, 64),
                user_agent=_clip(user_agent, 512),
            )
            logger.info(
                "操作日志写入成功 log_id=%s username=%s module=%s action=%s status=%s",
                log.id,
                log.username,
                log.module,
                log.action,
                log.status,
            )
            return log
        except Exception:
            self.repository.rollback()
            logger.exception("操作日志写入失败 module=%s action=%s status=%s", module, action, status)
            return None

    def list_logs(
        self,
        *,
        page: int,
        page_size: int,
        username: str | None = None,
        module: str | None = None,
        action: str | None = None,
        status: str | None = None,
        keyword: str | None = None,
        start_time: datetime | None = None,
        end_time: datetime | None = None,
    ) -> OperationLogPage:
        safe_page = max(page, 1)
        safe_page_size = min(max(page_size, 1), 100)
        clean_username = _clean_optional(username)
        clean_module = _clean_optional(module)
        clean_action = _clean_optional(action)
        clean_status = _clean_optional(status)
        clean_keyword = _clean_optional(keyword)
        items, total = self.repository.list_logs(
            page=safe_page,
            page_size=safe_page_size,
            username=clean_username,
            module=clean_module,
            action=clean_action,
            status=clean_status,
            keyword=clean_keyword,
            start_time=start_time,
            end_time=end_time,
        )
        logger.info("查询操作日志成功 total=%s page=%s page_size=%s", total, safe_page, safe_page_size)
        return OperationLogPage(items=items, total=total, page=safe_page, page_size=safe_page_size)


def _clean_optional(value: str | None) -> str | None:
    if value is None:
        return None
    stripped = value.strip()
    return stripped or None


def _clip(value: str, max_length: int) -> str:
    return value[:max_length]
