import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
  NotFoundException,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { GenerateReportDto } from '../dto/request/generate-report.dto';
import { QueryReportDto } from '../dto/request/query-report.dto';
import { ReportSnapshotResponseDto } from '../dto/response/report-snapshot.dto';
import { ReportDefinitionResponseDto } from '../dto/response/report-definition.dto';
import { GenerateReportHandler } from '../../application/commands/generate-report/generate-report.handler';
import { GenerateReportCommand } from '../../application/commands/generate-report/generate-report.command';
import { ReportingApplicationService } from '../../application/services/reporting-application.service';

@ApiTags('Reports')
@Controller('reports')
@ApiBearerAuth()
export class ReportController {
  constructor(
    private readonly generateReportHandler: GenerateReportHandler,
    private readonly reportingService: ReportingApplicationService,
  ) {}

  @Get('definitions')
  @ApiOperation({ summary: '获取所有报表定义' })
  @ApiResponse({
    status: 200,
    description: '报表定义列表',
    type: [ReportDefinitionResponseDto],
  })
  async getDefinitions(): Promise<ReportDefinitionResponseDto[]> {
    return this.reportingService.getReportDefinitions();
  }

  @Get('definitions/:code')
  @ApiOperation({ summary: '获取报表定义详情' })
  @ApiResponse({
    status: 200,
    description: '报表定义详情',
    type: ReportDefinitionResponseDto,
  })
  @ApiResponse({ status: 404, description: '报表定义不存在' })
  async getDefinition(
    @Param('code') code: string,
  ): Promise<ReportDefinitionResponseDto> {
    const definition = await this.reportingService.getReportDefinitionByCode(code);
    if (!definition) {
      throw new NotFoundException(`Report definition not found: ${code}`);
    }
    return definition;
  }

  @Post('generate')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: '生成报表' })
  @ApiResponse({
    status: 200,
    description: '报表生成成功',
    type: ReportSnapshotResponseDto,
  })
  async generateReport(
    @Body() dto: GenerateReportDto,
  ): Promise<ReportSnapshotResponseDto> {
    const command = new GenerateReportCommand(
      dto.reportCode,
      dto.reportPeriod,
      new Date(dto.startDate),
      new Date(dto.endDate),
      dto.dimensions,
      dto.filters,
    );

    const snapshot = await this.generateReportHandler.execute(command);

    return {
      id: snapshot.id?.toString() || '',
      reportType: snapshot.reportType,
      reportCode: snapshot.reportCode,
      reportPeriod: snapshot.reportPeriod,
      periodKey: snapshot.periodKey,
      rowCount: snapshot.rowCount,
      summary: snapshot.snapshotData.summary,
      rows: snapshot.snapshotData.rows,
      periodStartAt: snapshot.periodStartAt,
      periodEndAt: snapshot.periodEndAt,
      generatedAt: snapshot.generatedAt,
    };
  }

  @Get('snapshots')
  @ApiOperation({ summary: '查询报表快照' })
  @ApiResponse({
    status: 200,
    description: '报表快照列表',
    type: [ReportSnapshotResponseDto],
  })
  async getSnapshots(
    @Query() query: QueryReportDto,
  ): Promise<ReportSnapshotResponseDto[]> {
    if (query.reportCode) {
      const snapshots = await this.reportingService.getReportSnapshots(
        query.reportCode,
      );
      return snapshots.map((s) => ({
        ...s,
        rows: undefined,
      }));
    }

    if (query.reportPeriod) {
      const snapshots = await this.reportingService.getSnapshotsByPeriod(
        query.reportPeriod,
      );
      return snapshots.map((s) => ({
        ...s,
        rows: undefined,
      }));
    }

    return [];
  }

  @Get('snapshots/:code/latest')
  @ApiOperation({ summary: '获取最新报表快照' })
  @ApiResponse({
    status: 200,
    description: '最新报表快照',
    type: ReportSnapshotResponseDto,
  })
  @ApiResponse({ status: 404, description: '快照不存在' })
  async getLatestSnapshot(
    @Param('code') code: string,
  ): Promise<ReportSnapshotResponseDto> {
    const snapshot = await this.reportingService.getLatestSnapshot(code);
    if (!snapshot) {
      throw new NotFoundException(`No snapshot found for report: ${code}`);
    }
    return {
      ...snapshot,
      rows: undefined,
    };
  }
}
