/**
 * 结构化日志服务
 * 
 * 提供 ELK/CloudWatch 兼容的 JSON 结构化日志格式
 * 支持多种输出方式：Console、File、JSON
 */

import { Injectable } from '@nestjs/common';
import { TraceContext } from './trace-context.service';

// 结构化日志接口（ELK 兼容）
export interface StructuredLog {
  // 基础字段
  '@timestamp': string;        // ISO 8601 格式
  level: string;               // ERROR | WARN | INFO | DEBUG
  message: string;             // 日志消息
  
  // 追踪字段
  trace?: {
    id: string;                // traceId
    span_id: string;           // spanId
    parent_span_id?: string;   // parentSpanId
  };
  
  // 请求字段
  http?: {
    request_id: string;        // RequestID
    method: string;            // HTTP 方法
    url: string;               // 请求 URL
    status_code: number;       // 响应状态码
    duration_ms: number;       // 响应时间
  };
  
  // 用户字段
  user?: {
    id: string;                // userId
    name: string;              // username
  };
  
  // 客户端字段
  client?: {
    ip: string;                // IP 地址
    user_agent: string;        // User-Agent
    geo?: {
      country?: string;
      city?: string;
    };
  };
  
  // 服务字段
  service: {
    name: string;              // IAM | Form | Approval
    version: string;           // 服务版本
    instance: string;          // 实例 ID
    region: string;            // CN | US | UAE
  };
  
  // Temporal 字段（可选）
  temporal?: {
    workflow_id: string;
    workflow_type: string;
    workflow_run_id?: string;
    activity_id?: string;
    activity_type?: string;
    attempt?: number;
  };
  
  // 错误字段（可选）
  error?: {
    type: string;              // 错误类型
    message: string;           // 错误消息
    code?: string;             // 错误代码
    stack?: string;            // 堆栈信息（仅开发环境）
    details?: Record<string, any>; // 详细信息
  };

  // 额外元数据
  metadata?: Record<string, any>;
}

// HTTP 日志输入
export interface HttpLogInput {
  traceContext: TraceContext;
  requestId: string;
  method: string;
  url: string;
  statusCode: number;
  durationMs: number;
  userId?: string;
  userName?: string;
  clientIp?: string;
  userAgent?: string;
  error?: {
    type: string;
    message: string;
    code?: string;
    stack?: string;
    details?: Record<string, any>;
  };
  metadata?: Record<string, any>;
}

// Temporal 日志输入
export interface TemporalLogInput {
  traceContext?: TraceContext;
  workflowId: string;
  workflowType: string;
  workflowRunId?: string;
  activityId?: string;
  activityType?: string;
  attempt?: number;
  status: 'STARTED' | 'COMPLETED' | 'FAILED' | 'RETRYING';
  durationMs?: number;
  error?: {
    type: string;
    message: string;
  };
  metadata?: Record<string, any>;
}

@Injectable()
export class StructuredLoggerService {
  private readonly serviceName: string;
  private readonly serviceVersion: string;
  private readonly serviceInstance: string;
  private readonly serviceRegion: string;
  private readonly isDevelopment: boolean;

  constructor() {
    this.serviceName = process.env.LOG_SERVICE || 'Backend';
    this.serviceVersion = process.env.npm_package_version || '1.0.0';
    this.serviceInstance = process.env.LOG_INSTANCE || process.env.HOSTNAME || 'local';
    this.serviceRegion = process.env.LOG_REGION || process.env.REGION || 'CN';
    this.isDevelopment = process.env.NODE_ENV === 'development';
  }

  /**
   * 构造日志公共字段（@timestamp + level + message + service + 可选 trace）
   */
  private baseLog(level: string, message: string, traceContext?: TraceContext): StructuredLog {
    const log: StructuredLog = {
      '@timestamp': new Date().toISOString(),
      level: level.toUpperCase(),
      message,
      service: {
        name: this.serviceName,
        version: this.serviceVersion,
        instance: this.serviceInstance,
        region: this.serviceRegion,
      },
    };

    if (traceContext) {
      log.trace = {
        id: traceContext.traceId,
        span_id: traceContext.spanId,
        parent_span_id: traceContext.parentSpanId,
      };
    }

    return log;
  }

  /**
   * 创建 HTTP 请求日志
   */
  createHttpLog(level: string, message: string, input: HttpLogInput): StructuredLog {
    const log = this.baseLog(level, message, input.traceContext);

    log.http = {
      request_id: input.requestId,
      method: input.method,
      url: input.url,
      status_code: input.statusCode,
      duration_ms: input.durationMs,
    };

    if (input.userId) {
      log.user = { id: input.userId, name: input.userName || '' };
    }

    if (input.clientIp || input.userAgent) {
      log.client = { ip: input.clientIp || '', user_agent: input.userAgent || '' };
    }

    if (input.error) {
      log.error = {
        type: input.error.type,
        message: input.error.message,
        code: input.error.code,
        stack: this.isDevelopment ? input.error.stack : undefined,
        details: input.error.details,
      };
    }

    if (input.metadata) {
      log.metadata = input.metadata;
    }

    return log;
  }

  /**
   * 创建 Temporal 工作流日志
   */
  createTemporalLog(level: string, message: string, input: TemporalLogInput): StructuredLog {
    const log = this.baseLog(level, message, input.traceContext);

    log.temporal = {
      workflow_id: input.workflowId,
      workflow_type: input.workflowType,
      workflow_run_id: input.workflowRunId,
      activity_id: input.activityId,
      activity_type: input.activityType,
      attempt: input.attempt,
    };

    if (input.error) {
      log.error = { type: input.error.type, message: input.error.message };
    }

    log.metadata = {
      ...(input.metadata ?? {}),
      status: input.status,
      duration_ms: input.durationMs,
    };

    return log;
  }

  /**
   * 创建通用日志
   */
  createLog(
    level: string,
    message: string,
    options?: {
      traceContext?: TraceContext;
      error?: { type: string; message: string; code?: string; stack?: string };
      metadata?: Record<string, any>;
    },
  ): StructuredLog {
    const log = this.baseLog(level, message, options?.traceContext);

    if (options?.error) {
      log.error = {
        type: options.error.type,
        message: options.error.message,
        code: options.error.code,
        stack: this.isDevelopment ? options.error.stack : undefined,
      };
    }

    if (options?.metadata) {
      log.metadata = options.metadata;
    }

    return log;
  }

  /**
   * 格式化为 JSON 字符串
   */
  toJson(log: StructuredLog): string {
    return JSON.stringify(log);
  }

  /**
   * 格式化为人类可读的字符串（用于控制台）
   */
  toReadable(log: StructuredLog): string {
    const levelEmoji = this.getLevelEmoji(log.level);
    const timestamp = log['@timestamp'].substring(11, 23); // HH:mm:ss.SSS

    let output = `${timestamp} ${levelEmoji} ${log.level.padEnd(5)} ${log.message}`;

    if (log.trace) {
      output += ` | trace=${log.trace.id}`;
    }

    if (log.http) {
      output += ` | ${log.http.method} ${log.http.url} ${log.http.status_code} ${log.http.duration_ms}ms`;
    }

    if (log.user) {
      output += ` | user=${log.user.name}(${log.user.id})`;
    }

    if (log.error) {
      output += ` | error=${log.error.type}: ${log.error.message}`;
    }

    return output;
  }

  /**
   * 获取日志级别对应的 emoji
   */
  private getLevelEmoji(level: string): string {
    switch (level.toUpperCase()) {
      case 'ERROR': return '❌';
      case 'WARN': return '⚠️';
      case 'INFO': return '✅';
      case 'DEBUG': return '🔍';
      default: return '📝';
    }
  }
}

