import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Query,
  Param,
  UseGuards,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiResponse,
  ApiParam,
} from '@nestjs/swagger';
import { EmailType } from '@prisma/client';
import { EmailService } from './email.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { ModuleGuard } from '../../common/guards/module.guard';
import { Roles, UserRole } from '../../common/decorators/roles.decorator';
import { RequireModule } from '../../common/decorators/require-module.decorator';
import {
  CurrentUser,
  JwtPayload,
} from '../../common/decorators/current-user.decorator';
import { SendEmailDto, UpsertEmailTemplateDto, FindEmailLogsDto } from './dto';

@ApiTags('Email')
@ApiBearerAuth()
@Controller('email')
@UseGuards(JwtAuthGuard, ModuleGuard, RolesGuard)
@RequireModule('email')
@Roles(UserRole.CLUB_ADMIN, UserRole.SUPER_ADMIN)
export class EmailController {
  constructor(private readonly emailService: EmailService) {}

  // ─── Templates ──────────────────────────────────────────────────

  @Get('templates')
  @ApiOperation({ summary: 'List all email templates for the club' })
  @ApiResponse({ status: 200, description: 'List of email templates' })
  async findTemplates(@CurrentUser() user: JwtPayload) {
    return this.emailService.findTemplates(user.clubId);
  }

  @Get('templates/:type')
  @ApiOperation({ summary: 'Get email template by type' })
  @ApiParam({ name: 'type', enum: EmailType })
  @ApiResponse({ status: 200, description: 'Email template' })
  @ApiResponse({ status: 404, description: 'Template not found' })
  async findTemplate(
    @CurrentUser() user: JwtPayload,
    @Param('type') type: EmailType,
  ) {
    return this.emailService.findTemplateByType(user.clubId, type);
  }

  @Put('templates')
  @ApiOperation({ summary: 'Create or update an email template' })
  @ApiResponse({ status: 200, description: 'Template saved' })
  async upsertTemplate(
    @CurrentUser() user: JwtPayload,
    @Body() dto: UpsertEmailTemplateDto,
  ) {
    return this.emailService.upsertTemplate(user.clubId, dto);
  }

  @Delete('templates/:type')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Delete an email template' })
  @ApiParam({ name: 'type', enum: EmailType })
  @ApiResponse({ status: 204, description: 'Template deleted' })
  @ApiResponse({ status: 404, description: 'Template not found' })
  async deleteTemplate(
    @CurrentUser() user: JwtPayload,
    @Param('type') type: EmailType,
  ) {
    await this.emailService.deleteTemplate(user.clubId, type);
  }

  // ─── Send ───────────────────────────────────────────────────────

  @Post('send')
  @ApiOperation({ summary: 'Send an email to a recipient' })
  @ApiResponse({ status: 201, description: 'Email queued for sending' })
  async send(
    @CurrentUser() user: JwtPayload,
    @Body() dto: SendEmailDto,
  ) {
    return this.emailService.send(user.clubId, dto);
  }

  @Post('send-bulk')
  @ApiOperation({ summary: 'Send emails in bulk' })
  @ApiResponse({ status: 201, description: 'Emails queued for sending' })
  async sendBulk(
    @CurrentUser() user: JwtPayload,
    @Body() emails: SendEmailDto[],
  ) {
    return this.emailService.sendBulk(user.clubId, emails);
  }

  // ─── Logs & Stats ──────────────────────────────────────────────

  @Get('logs')
  @ApiOperation({ summary: 'List email send logs' })
  @ApiResponse({ status: 200, description: 'Paginated list of email logs' })
  async findLogs(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindEmailLogsDto,
  ) {
    return this.emailService.findLogs(user.clubId, query);
  }

  @Get('stats')
  @ApiOperation({ summary: 'Get email sending statistics' })
  @ApiResponse({ status: 200, description: 'Email stats (total, sent, delivered, opened, failed)' })
  async getStats(@CurrentUser() user: JwtPayload) {
    return this.emailService.getStats(user.clubId);
  }

  // ─── Tracking webhook ──────────────────────────────────────────

  @Post('tracking')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Webhook for email delivery status updates' })
  @ApiResponse({ status: 200, description: 'Status updated' })
  async trackingWebhook(
    @Body() body: { messageId: string; event: string },
  ) {
    const statusMap: Record<string, 'DELIVERED' | 'OPENED' | 'CLICKED' | 'BOUNCED'> = {
      delivered: 'DELIVERED',
      opened: 'OPENED',
      clicked: 'CLICKED',
      bounced: 'BOUNCED',
      bounce: 'BOUNCED',
    };

    const status = statusMap[body.event];
    if (status && body.messageId) {
      await this.emailService.updateStatus(body.messageId, status);
    }

    return { ok: true };
  }
}
