# -*- coding: utf-8 -*-
"""
audit_service.py — 操作日志查询服务

提供日志分页查询、用户列表、模块操作类型定义等功能。
"""

import json
import os
from datetime import datetime
from pathlib import Path
from typing import Optional, List, Dict, Any
from utils.paths import AUDIT_LOG_FILE

# 模块操作类型常量
MODULE_ACTIONS = {
    'troubleshoot': ['search', 'analyze', 'export', 'submit'],
    'monitor': ['create_target', 'edit_target', 'delete_target',
                'run_check', 'export_report', 'create_schedule',
                'edit_schedule', 'delete_schedule', 'config_notification'],
    'manage': ['auth_change', 'upgrade', 'query_info'],
    'auth': ['login', 'logout', 'login_failed']
}

# 操作类型中文映射
ACTION_LABELS = {
    'search': '搜索',
    'analyze': '分析',
    'export': '导出',
    'submit': '入库',
    'create_target': '创建目标',
    'edit_target': '编辑目标',
    'delete_target': '删除目标',
    'run_check': '执行巡检',
    'export_report': '导出报告',
    'create_schedule': '创建定时任务',
    'edit_schedule': '编辑定时任务',
    'delete_schedule': '删除定时任务',
    'config_notification': '配置通知',
    'auth_change': '授权变更',
    'upgrade': '升级操作',
    'query_info': '信息查询',
    'login': '登录',
    'logout': '退出',
    'login_failed': '登录失败',
    'clear_cache': '清除缓存',
}


def get_logs(
    module: str,
    page: int = 1,
    page_size: int = 20,
    start_time: Optional[str] = None,
    end_time: Optional[str] = None,
    action_type: Optional[str] = None,
    user: Optional[str] = None
) -> Dict[str, Any]:
    """分页查询操作日志

    Args:
        module: 模块名 (troubleshoot/monitor/manage/auth)
        page: 页码
        page_size: 每页条数
        start_time: 开始时间 ISO 格式
        end_time: 结束时间 ISO 格式
        action_type: 操作类型筛选
        user: 用户筛选

    Returns:
        dict: {total, page, pageSize, items: [...]}
    """
    if not AUDIT_LOG_FILE.exists():
        return {
            'total': 0,
            'page': page,
            'pageSize': page_size,
            'items': []
        }

    # 读取所有日志（倒序）
    all_logs = []
    try:
        with open(AUDIT_LOG_FILE, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                    # 补充 module 字段（兼容旧日志）
                    if 'module' not in entry:
                        entry['module'] = _infer_module_from_action(entry)
                    all_logs.append(entry)
                except json.JSONDecodeError:
                    continue
    except Exception:
        pass

    # 按时间倒序
    all_logs.reverse()

    # 过滤
    filtered = []
    for entry in all_logs:
        # 模块过滤
        entry_module = entry.get('module', '')
        if module == 'troubleshoot':
            # troubleshoot 模块包含 troubleshoot + auth + cache
            if entry_module not in ('troubleshoot', 'auth', ''):
                continue
        elif module == 'monitor':
            if entry_module != 'monitor':
                continue
        elif module == 'manage':
            if entry_module != 'manage':
                continue
        else:
            if entry_module != module:
                continue

        # 时间过滤
        timestamp = entry.get('timestamp', '')
        if start_time and timestamp:
            try:
                ts = datetime.fromisoformat(timestamp.replace('Z', '+00:00').replace('+00:00', ''))
                st = datetime.fromisoformat(start_time.replace('Z', '+00:00').replace('+00:00', ''))
                if ts < st:
                    continue
            except Exception:
                pass
        if end_time and timestamp:
            try:
                ts = datetime.fromisoformat(timestamp.replace('Z', '+00:00').replace('+00:00', ''))
                et = datetime.fromisoformat(end_time.replace('Z', '+00:00').replace('+00:00', ''))
                if ts > et:
                    continue
            except Exception:
                pass

        # 操作类型过滤
        if action_type:
            entry_action = entry.get('action', '') or _infer_action_from_entry(entry)
            if entry_action != action_type:
                continue

        # 用户过滤
        if user:
            entry_user = entry.get('user', '')
            if entry_user != user:
                continue

        filtered.append(entry)

    # 分页
    total = len(filtered)
    start_idx = (page - 1) * page_size
    end_idx = start_idx + page_size
    items = filtered[start_idx:end_idx]

    # 格式化输出
    formatted_items = []
    for i, entry in enumerate(items, start=start_idx + 1):
        formatted_items.append({
            'id': i,
            'timestamp': entry.get('timestamp', ''),
            'user': entry.get('user', entry.get('username', '')),
            'module': entry.get('module', ''),
            'action': entry.get('action', '') or _infer_action_from_entry(entry),
            'actionLabel': ACTION_LABELS.get(entry.get('action', ''), entry.get('action', '')),
            'target': entry.get('target', '') or _extract_target_from_entry(entry),
            'ip': entry.get('ip', entry.get('client_ip', '')),
            'details': entry
        })

    return {
        'total': total,
        'page': page,
        'pageSize': page_size,
        'items': formatted_items
    }


def get_users_with_logs(module: Optional[str] = None) -> List[str]:
    """获取有操作记录的用户列表

    Args:
        module: 模块筛选（可选）

    Returns:
        list: 用户名列表
    """
    if not AUDIT_LOG_FILE.exists():
        return []

    users = set()
    try:
        with open(AUDIT_LOG_FILE, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                    # 模块过滤
                    if module:
                        entry_module = entry.get('module', '')
                        if module == 'troubleshoot' and entry_module not in ('troubleshoot', 'auth', ''):
                            continue
                        elif module == 'monitor' and entry_module != 'monitor':
                            continue
                        elif module == 'manage' and entry_module != 'manage':
                            continue
                    # 提取用户
                    user = entry.get('user', entry.get('username', ''))
                    if user:
                        users.add(user)
                except json.JSONDecodeError:
                    continue
    except Exception:
        pass

    return sorted(list(users))


def _infer_module_from_action(entry: Dict) -> str:
    """从日志条目推断模块（兼容旧日志）"""
    # 根据字段特征推断
    if 'query' in entry or 'matched_count' in entry:
        return 'troubleshoot'
    if 'target_id' in entry or 'report_id' in entry or 'schedule_id' in entry:
        return 'monitor'
    if 'username' in entry and 'action' in entry:
        return 'auth'
    return 'troubleshoot'  # 默认


def _infer_action_from_entry(entry: Dict) -> str:
    """从日志条目推断操作类型（兼容旧日志）"""
    # 如果有明确的 action 字段
    if 'action' in entry:
        return entry['action']

    # 根据字段特征推断
    if 'query' in entry:
        if entry.get('mode', '') in ('stream', 'offline_stream'):
            return 'analyze'
        return 'search'
    if 'export_format' in entry:
        return 'export'
    if 'record_file' in entry or 'title' in entry:
        return 'submit'
    if entry.get('action') == 'login':
        return 'login'
    if entry.get('action') == 'logout':
        return 'logout'

    return ''


def _extract_target_from_entry(entry: Dict) -> str:
    """从日志条目提取操作对象摘要"""
    # 搜索关键字
    query = entry.get('query', '')
    if query:
        return query[:50] + ('...' if len(query) > 50 else '')

    # 用户名
    username = entry.get('username', '')
    if username:
        return f"用户: {username}"

    # 导出
    export_format = entry.get('export_format', '')
    if export_format:
        return f"导出格式: {export_format}"

    # 项目名
    project = entry.get('project', '')
    if project:
        return f"项目: {project}"

    return ''