import { UserType } from '@gadmin2n/nest-common';
import { CacheInterceptor, CacheTTL } from '@nestjs/cache-manager';
import {
  BadRequestException,
  Body,
  Controller,
  Get,
  Inject,
  Post,
  Query,
  Req,
  Res,
  UseInterceptors,
} from '@nestjs/common';
import {
  ApiOkResponse,
  ApiOperation,
  ApiProperty,
  ApiQuery,
} from '@nestjs/swagger';
import { trace } from '@opentelemetry/api';
import { Request, Response } from 'express';
import { UseRoles } from 'nest-access-control';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { PrismaService } from 'nestjs-prisma';
import * as path from 'path';
import { Logger } from 'winston';
import { AppService } from './app.service';
import { AllowUnauthorizedRequest } from './lib/auth.guard';

class UserInfo {
  @ApiProperty()
  userid: string;

  @ApiProperty()
  username: string;
}
@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly prisma: PrismaService,
    @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
  ) {
    this.logger = this.logger.child({
      file: path.basename(__filename),
    });
  }

  @Get('userinfo')
  @ApiOkResponse({ type: UserInfo })
  userInfo(@Req() request: Request & { user: UserType }) {
    return request?.user || { userid: '', username: '' };
  }

  @Get('hello')
  hello(): string {
    this.logger.info('hello');
    return this.appService.getHello();
  }

  /**
   * 调试端点：验证 Prisma OpenTelemetry tracing 是否正常工作
   * 调用后查看 APM 中是否有 prisma:client:* 和 prisma:engine:* spans
   */
  @Get('debug/tracing')
  @AllowUnauthorizedRequest()
  @ApiOperation({ summary: '调试 Prisma tracing' })
  async debugTracing() {
    const globalAny = global as any;
    const currentSpan = trace.getActiveSpan();
    const spanContext = currentSpan?.spanContext();

    // 执行一个简单的 Prisma 查询来触发 tracing
    const userCount = await this.prisma.user.count();

    return {
      message: 'Prisma tracing debug endpoint',
      tracerProvider: trace.getTracerProvider()?.constructor?.name,
      currentSpan: {
        traceId: spanContext?.traceId,
        spanId: spanContext?.spanId,
        traceFlags: spanContext?.traceFlags,
        sampled: spanContext?.traceFlags === 1,
      },
      prismaInstrumentation: {
        PRISMA_INSTRUMENTATION: !!globalAny.PRISMA_INSTRUMENTATION,
        V6_PRISMA_INSTRUMENTATION: !!globalAny.V6_PRISMA_INSTRUMENTATION,
        helperEnabled:
          globalAny.PRISMA_INSTRUMENTATION?.helper?.isEnabled() ?? false,
      },
      testQuery: {
        userCount,
      },
      env: {
        OTEL_SERVICE_NAME: process.env.OTEL_SERVICE_NAME,
        OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
      },
    };
  }

  @UseInterceptors(CacheInterceptor)
  @CacheTTL(10 * 1000) //10 seconds
  @Get('get-number')
  getNumber(): number {
    // 随机生成一个0-100之间的数字
    return Math.floor(Math.random() * 100);
  }

  @Get('login-callback')
  @AllowUnauthorizedRequest()
  loginCallback(@Req() request: Request, @Res() res) {
    return this.appService.loginCallback(request, res);
  }

  @Get('login')
  @AllowUnauthorizedRequest()
  login(@Req() request: Request, @Res() res) {
    return this.appService.login(request, res);
  }

  @Get('logout')
  @AllowUnauthorizedRequest()
  logout(@Req() request: Request, @Res() res) {
    return this.appService.logout(request, res);
  }

  // ============ External Page 路由 ============

  @Get('gtdr-page/sign-url')
  @UseRoles({
    resource: 'gtdrReport',
    action: 'create',
    possession: 'any',
  })
  @ApiOperation({ summary: '获取带签名的外部页面访问URL，302重定向' })
  @ApiQuery({ name: 'domain', required: true, description: 'Domain 编码' })
  @ApiQuery({ name: 'pageCode', required: true, description: '页面编码' })
  getExternalPageSignedUrl(
    @Query('domain') domain: string,
    @Query('pageCode') pageCode: string,
    @Req() req: Request & { user?: UserType },
    @Res() res: Response,
  ): void {
    if (!domain) {
      throw new BadRequestException('domain is required');
    }
    if (!pageCode) {
      throw new BadRequestException('pageCode is required');
    }

    const userid = req.user?.userid || 'anonymous';

    this.logger.info(
      `external_page_sign_url_request - 请求签名URL - userid: ${userid}, domain: ${domain}, pageCode: ${pageCode}`,
    );

    const { url } = this.appService.generateExternalPageSignedUrl(
      domain,
      pageCode,
      userid,
    );
    res.redirect(302, url);
  }

  @Post('external-page/verify')
  @ApiOperation({ summary: '验证外部页面签名（用于测试）' })
  verifyExternalPageSignature(
    @Body()
    body: {
      domain: string;
      pageCode: string;
      userid: string;
      timestamp: string;
      signature: string;
    },
  ): { valid: boolean; reason?: string } {
    const { domain, pageCode, userid, timestamp, signature } = body;

    if (!domain || !pageCode || !userid || !timestamp || !signature) {
      throw new BadRequestException('Missing required parameters');
    }

    return this.appService.verifyExternalPageSignature(
      domain,
      pageCode,
      userid,
      timestamp,
      signature,
    );
  }
}
