"""
Audit Log Service

操作审计日志服务，用于记录和查询审计日志。
"""

import logging
from typing import Optional, List, Dict, Any, Tuple
from datetime import datetime
import csv
import io

from sqlmodel import Session, select, func
from src.config.database import engine
from src.models.audit_log import AuditLogDB

logger = logging.getLogger(__name__)


class AuditLogService:
    """审计日志服务"""

    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def log_action(
        self,
        user_id: Optional[str],
        username: Optional[str],
        action: str,
        resource_type: Optional[str] = None,
        resource_id: Optional[str] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None,
        details: Optional[Dict[str, Any]] = None,
    ) -> AuditLogDB:
        """
        记录操作日志

        Args:
            user_id: 用户 ID
            username: 用户名
            action: 操作类型
            resource_type: 资源类型
            resource_id: 资源 ID
            ip_address: IP 地址
            user_agent: 用户代理
            details: 详细信息

        Returns:
            创建的审计日志记录
        """
        with Session(engine) as session:
            audit_log = AuditLogDB(
                user_id=user_id,
                username=username,
                action=action,
                resource_type=resource_type,
                resource_id=resource_id,
                ip_address=ip_address,
                user_agent=user_agent,
                details=details or {},
            )
            session.add(audit_log)
            session.commit()
            session.refresh(audit_log)

            logger.info(f"Audit log: {action} by {username or user_id or 'unknown'}")
            return audit_log

    def list_logs(
        self,
        page: int = 1,
        page_size: int = 20,
        filters: Optional[Dict[str, Any]] = None,
        sort_by: str = "created_at",
        sort_order: str = "desc",
    ) -> Tuple[List[AuditLogDB], int]:
        """
        查询审计日志

        Args:
            page: 页码
            page_size: 每页数量
            filters: 过滤条件
            sort_by: 排序字段
            sort_order: 排序方向

        Returns:
            (日志列表，总数)
        """
        with Session(engine) as session:
            query = select(AuditLogDB)

            # 应用过滤
            if filters:
                if filters.get("user_id"):
                    query = query.where(AuditLogDB.user_id == filters["user_id"])
                if filters.get("action"):
                    query = query.where(AuditLogDB.action.like(f"%{filters['action']}%"))
                if filters.get("resource_type"):
                    query = query.where(AuditLogDB.resource_type == filters["resource_type"])
                if filters.get("resource_id"):
                    query = query.where(AuditLogDB.resource_id == filters["resource_id"])
                if filters.get("start_date"):
                    try:
                        start_ts = datetime.fromisoformat(filters["start_date"]).timestamp()
                        query = query.where(AuditLogDB.created_at >= start_ts)
                    except (ValueError, TypeError):
                        pass  # 忽略无效的日期格式
                if filters.get("end_date"):
                    try:
                        end_ts = datetime.fromisoformat(filters["end_date"]).timestamp()
                        query = query.where(AuditLogDB.created_at <= end_ts)
                    except (ValueError, TypeError):
                        pass  # 忽略无效的日期格式

            # 获取总数
            total = session.exec(
                select(func.count()).select_from(query.subquery())
            ).one()

            # 应用排序
            if sort_by == "created_at":
                sort_column = AuditLogDB.created_at
            elif sort_by == "action":
                sort_column = AuditLogDB.action
            elif sort_by == "username":
                sort_column = AuditLogDB.username
            else:
                sort_column = AuditLogDB.created_at

            if sort_order.lower() == "desc":
                query = query.order_by(sort_column.desc())
            else:
                query = query.order_by(sort_column.asc())

            # 应用分页
            offset = (page - 1) * page_size
            query = query.offset(offset).limit(page_size)

            results = session.exec(query).all()
            return results, total

    def get_log(self, log_id: str) -> Optional[AuditLogDB]:
        """
        获取审计日志详情

        Args:
            log_id: 日志 ID

        Returns:
            审计日志记录
        """
        with Session(engine) as session:
            return session.get(AuditLogDB, log_id)

    def export_logs(
        self,
        filters: Optional[Dict[str, Any]] = None,
    ) -> str:
        """
        导出审计日志为 CSV

        Args:
            filters: 过滤条件

        Returns:
            CSV 内容
        """
        # 获取所有匹配的日志（不分页）
        with Session(engine) as session:
            query = select(AuditLogDB)

            # 应用过滤
            if filters:
                if filters.get("user_id"):
                    query = query.where(AuditLogDB.user_id == filters["user_id"])
                if filters.get("action"):
                    query = query.where(AuditLogDB.action.like(f"%{filters['action']}%"))
                if filters.get("resource_type"):
                    query = query.where(AuditLogDB.resource_type == filters["resource_type"])
                if filters.get("start_date"):
                    try:
                        start_ts = datetime.fromisoformat(filters["start_date"]).timestamp()
                        query = query.where(AuditLogDB.created_at >= start_ts)
                    except (ValueError, TypeError):
                        pass  # 忽略无效的日期格式
                if filters.get("end_date"):
                    try:
                        end_ts = datetime.fromisoformat(filters["end_date"]).timestamp()
                        query = query.where(AuditLogDB.created_at <= end_ts)
                    except (ValueError, TypeError):
                        pass  # 忽略无效的日期格式

            query = query.order_by(AuditLogDB.created_at.desc())
            results = session.exec(query.limit(10000).all())

            # 生成 CSV
            output = io.StringIO()
            writer = csv.writer(output)

            # 写入表头
            writer.writerow([
                "ID", "User ID", "Username", "Action", "Resource Type",
                "Resource ID", "IP Address", "Details", "Created At"
            ])

            # 写入数据
            for log in results:
                writer.writerow([
                    log.id,
                    log.user_id or "",
                    log.username or "",
                    log.action,
                    log.resource_type or "",
                    log.resource_id or "",
                    log.ip_address or "",
                    str(log.details) if log.details else "",
                    datetime.fromtimestamp(log.created_at).isoformat(),
                ])

            return output.getvalue()


# 全局服务实例
audit_log_service = AuditLogService()
