import {
  Controller,
  Get,
  Post,
  Put,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiQuery,
} from '@nestjs/swagger';
import { GembaDocsService } from './gembadocs.service';
import {
  ListAuditsDto,
  CreateAuditDto,
  UpdateAuditDto,
  ListFindingsDto,
  UpdateFindingDto,
  ResolveFindingDto,
  GetTrendsDto,
  AuditResponseDto,
  AuditDetailResponseDto,
  FindingResponseDto,
  ChecklistResponseDto,
  ChecklistDetailResponseDto,
  StatisticsResponseDto,
  TrendResponseDto,
  PaginatedAuditsResponseDto,
  PaginatedFindingsResponseDto,
  AuditType,
  AuditStatus,
  FindingSeverity,
  FindingStatus,
} from './gembadocs.types';
import { RequirePermissions } from '../../../../auth/permissions/permissions.decorator';
import { Permission } from '../../../../auth/permissions/permissions.enum';

/**
 * GembaDocs Integration Controller
 *
 * REST API endpoints for GembaDocs audit and checklist management integration.
 */
@ApiTags('Integrations - GembaDocs')
@ApiBearerAuth()
@Controller('integrations/gembadocs')
export class GembaDocsController {
  constructor(private readonly gembaDocsService: GembaDocsService) {}

  // ============ Health & Status ============

  @Post('test')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Test GembaDocs connection' })
  @ApiResponse({
    status: 200,
    description: 'Connection test result',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        message: { type: 'string' },
        latency: { type: 'number' },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async testConnection() {
    return this.gembaDocsService.testConnection();
  }

  @Get('health')
  @ApiOperation({ summary: 'Get GembaDocs connector health status' })
  @ApiResponse({
    status: 200,
    description: 'Health status',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', enum: ['connected', 'error', 'not_configured'] },
        lastCheck: { type: 'string', format: 'date-time' },
        latency: { type: 'number' },
        error: { type: 'string' },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getHealth() {
    return this.gembaDocsService.checkHealth();
  }

  // ============ Audits ============

  @Get('audits')
  @ApiOperation({ summary: 'List audits with optional filters' })
  @ApiQuery({ name: 'type', required: false, enum: AuditType })
  @ApiQuery({ name: 'status', required: false, enum: AuditStatus })
  @ApiQuery({ name: 'department', required: false, type: String })
  @ApiQuery({ name: 'location', required: false, type: String })
  @ApiQuery({ name: 'auditorId', required: false, type: String })
  @ApiQuery({ name: 'dateFrom', required: false, type: String, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'dateTo', required: false, type: String, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({ status: 200, description: 'Paginated list of audits', type: PaginatedAuditsResponseDto })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listAudits(@Query() query: ListAuditsDto): Promise<PaginatedAuditsResponseDto> {
    return this.gembaDocsService.listAudits(query);
  }

  @Get('audits/upcoming')
  @ApiOperation({ summary: 'Get upcoming audits' })
  @ApiQuery({ name: 'days', required: false, type: Number, description: 'Days ahead to look (default: 7)' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Maximum results (default: 10)' })
  @ApiResponse({ status: 200, description: 'List of upcoming audits', type: [AuditResponseDto] })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getUpcomingAudits(
    @Query('days') days?: number,
    @Query('limit') limit?: number,
  ): Promise<AuditResponseDto[]> {
    return this.gembaDocsService.getUpcomingAudits(days || 7, limit || 10);
  }

  @Get('audits/overdue')
  @ApiOperation({ summary: 'Get overdue audits' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Maximum results (default: 10)' })
  @ApiResponse({ status: 200, description: 'List of overdue audits', type: [AuditResponseDto] })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getOverdueAudits(@Query('limit') limit?: number): Promise<AuditResponseDto[]> {
    return this.gembaDocsService.getOverdueAudits(limit || 10);
  }

  @Get('audits/:id')
  @ApiOperation({ summary: 'Get a single audit by ID' })
  @ApiParam({ name: 'id', type: String })
  @ApiResponse({ status: 200, description: 'Audit details', type: AuditDetailResponseDto })
  @ApiResponse({ status: 404, description: 'Audit not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getAudit(@Param('id') id: string): Promise<AuditDetailResponseDto> {
    return this.gembaDocsService.getAudit(id);
  }

  @Post('audits')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new audit' })
  @ApiResponse({ status: 201, description: 'Audit created', type: AuditDetailResponseDto })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async createAudit(@Body() data: CreateAuditDto): Promise<AuditDetailResponseDto> {
    return this.gembaDocsService.createAudit(data);
  }

  @Put('audits/:id')
  @ApiOperation({ summary: 'Update an audit' })
  @ApiParam({ name: 'id', type: String })
  @ApiResponse({ status: 200, description: 'Audit updated', type: AuditDetailResponseDto })
  @ApiResponse({ status: 404, description: 'Audit not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async updateAudit(
    @Param('id') id: string,
    @Body() data: UpdateAuditDto,
  ): Promise<AuditDetailResponseDto> {
    return this.gembaDocsService.updateAudit(id, data);
  }

  // ============ Checklists ============

  @Get('checklists')
  @ApiOperation({ summary: 'List all checklist templates' })
  @ApiResponse({ status: 200, description: 'List of checklists', type: [ChecklistResponseDto] })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listChecklists(): Promise<ChecklistResponseDto[]> {
    return this.gembaDocsService.listChecklists();
  }

  @Get('checklists/:id')
  @ApiOperation({ summary: 'Get a single checklist by ID' })
  @ApiParam({ name: 'id', type: String })
  @ApiResponse({ status: 200, description: 'Checklist details', type: ChecklistDetailResponseDto })
  @ApiResponse({ status: 404, description: 'Checklist not found' })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getChecklist(@Param('id') id: string): Promise<ChecklistDetailResponseDto> {
    return this.gembaDocsService.getChecklist(id);
  }

  // ============ Findings ============

  @Get('findings')
  @ApiOperation({ summary: 'List findings with optional filters' })
  @ApiQuery({ name: 'auditId', required: false, type: String })
  @ApiQuery({ name: 'severity', required: false, enum: FindingSeverity })
  @ApiQuery({ name: 'status', required: false, enum: FindingStatus })
  @ApiQuery({ name: 'assigneeId', required: false, type: String })
  @ApiQuery({ name: 'overdueOnly', required: false, type: Boolean })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiResponse({ status: 200, description: 'Paginated list of findings', type: PaginatedFindingsResponseDto })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async listFindings(@Query() query: ListFindingsDto): Promise<PaginatedFindingsResponseDto> {
    return this.gembaDocsService.listFindings(query);
  }

  @Get('findings/open')
  @ApiOperation({ summary: 'Get open findings' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Maximum results (default: 20)' })
  @ApiResponse({ status: 200, description: 'List of open findings', type: [FindingResponseDto] })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getOpenFindings(@Query('limit') limit?: number): Promise<FindingResponseDto[]> {
    return this.gembaDocsService.getOpenFindings(limit || 20);
  }

  @Put('findings/:id')
  @ApiOperation({ summary: 'Update a finding' })
  @ApiParam({ name: 'id', type: String })
  @ApiResponse({ status: 200, description: 'Finding updated', type: FindingResponseDto })
  @ApiResponse({ status: 404, description: 'Finding not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async updateFinding(
    @Param('id') id: string,
    @Body() data: UpdateFindingDto,
  ): Promise<FindingResponseDto> {
    return this.gembaDocsService.updateFinding(id, data);
  }

  @Post('findings/:id/resolve')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Resolve a finding' })
  @ApiParam({ name: 'id', type: String })
  @ApiResponse({ status: 200, description: 'Finding resolved', type: FindingResponseDto })
  @ApiResponse({ status: 404, description: 'Finding not found' })
  @RequirePermissions(Permission.INTEGRATIONS_MANAGE)
  async resolveFinding(
    @Param('id') id: string,
    @Body() data: ResolveFindingDto,
  ): Promise<FindingResponseDto> {
    return this.gembaDocsService.resolveFinding(id, data);
  }

  // ============ Statistics & Trends ============

  @Get('statistics')
  @ApiOperation({ summary: 'Get audit statistics' })
  @ApiQuery({ name: 'department', required: false, type: String })
  @ApiResponse({ status: 200, description: 'Audit statistics', type: StatisticsResponseDto })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getStatistics(@Query('department') department?: string): Promise<StatisticsResponseDto> {
    return this.gembaDocsService.getStatistics(department);
  }

  @Get('trends')
  @ApiOperation({ summary: 'Get trend data for charts' })
  @ApiQuery({ name: 'period', required: false, enum: ['week', 'month', 'quarter', 'year'] })
  @ApiQuery({ name: 'startDate', required: false, type: String, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'endDate', required: false, type: String, description: 'YYYY-MM-DD' })
  @ApiQuery({ name: 'department', required: false, type: String })
  @ApiQuery({ name: 'auditType', required: false, enum: AuditType })
  @ApiResponse({ status: 200, description: 'Trend data', type: TrendResponseDto })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getTrends(@Query() query: GetTrendsDto): Promise<TrendResponseDto> {
    return this.gembaDocsService.getTrends(query);
  }

  @Get('compliance-score')
  @ApiOperation({ summary: 'Get overall compliance score' })
  @ApiQuery({ name: 'threshold', required: false, type: Number, description: 'Score threshold (default: 80)' })
  @ApiResponse({
    status: 200,
    description: 'Compliance score with trend',
    schema: {
      type: 'object',
      properties: {
        score: { type: 'number' },
        trend: { type: 'string', enum: ['up', 'down', 'stable'] },
        change: { type: 'number' },
      },
    },
  })
  @RequirePermissions(Permission.INTEGRATIONS_VIEW)
  async getComplianceScore(@Query('threshold') threshold?: number) {
    return this.gembaDocsService.getComplianceScore(threshold || 80);
  }
}
