import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable, tap } from 'rxjs';
import { PrismaService } from '../../../database/prisma.service';
import { LOG_OPERATION_KEY, LogOperationOptions } from '../decorators/log-operation.decorator';

@Injectable()
export class LogInterceptor implements NestInterceptor {
  private readonly logger = new Logger(LogInterceptor.name);

  constructor(
    private reflector: Reflector,
    private prisma: PrismaService,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const logOptions = this.reflector.getAllAndOverride<LogOperationOptions>(
      LOG_OPERATION_KEY,
      [context.getHandler(), context.getClass()],
    );

    if (!logOptions) {
      return next.handle();
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const startTime = Date.now();

    // 获取请求体（用于记录变更前后数据）
    const body = request.body;
    const params = request.params;

    return next.handle().pipe(
      tap({
        next: (response) => {
          this.saveLog({
            user,
            logOptions,
            body,
            params,
            response,
            ipAddress: this.getIpAddress(request),
            userAgent: request.headers['user-agent'],
            duration: Date.now() - startTime,
          });
        },
        error: (error) => {
          // 错误情况下也记录日志
          this.saveLog({
            user,
            logOptions,
            body,
            params,
            response: { error: error.message },
            ipAddress: this.getIpAddress(request),
            userAgent: request.headers['user-agent'],
            duration: Date.now() - startTime,
            isError: true,
          });
        },
      }),
    );
  }

  private async saveLog(data: {
    user: any;
    logOptions: LogOperationOptions;
    body: any;
    params: any;
    response: any;
    ipAddress: string;
    userAgent: string;
    duration: number;
    isError?: boolean;
  }) {
    try {
      const { user, logOptions, body, params, response, ipAddress, userAgent } = data;

      // 获取目标ID
      let targetId: number | undefined;
      if (params?.id) {
        targetId = parseInt(params.id, 10);
      } else if (response?.id) {
        targetId = response.id;
      } else if (body?.id) {
        targetId = body.id;
      }

      // 构建描述
      let description = logOptions.description;
      if (data.isError) {
        description = `[失败] ${description}`;
      }

      await this.prisma.operationLog.create({
        data: {
          tenantId: user?.tenantId || null,
          userId: user?.userId || 0,
          userType: user?.role || 'UNKNOWN',
          action: logOptions.action,
          module: logOptions.module,
          description,
          targetId,
          oldValue: body ? JSON.stringify(body) : null,
          newValue: response ? JSON.stringify(response) : null,
          ipAddress,
          userAgent,
        },
      });

      this.logger.debug(
        `Operation logged: ${logOptions.module} - ${logOptions.action} (${data.duration}ms)`
      );
    } catch (error) {
      this.logger.error('Failed to save operation log:', error);
    }
  }

  private getIpAddress(request: any): string {
    return (
      request.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
      request.headers['x-real-ip'] ||
      request.connection?.remoteAddress ||
      request.socket?.remoteAddress ||
      'unknown'
    );
  }
}
