import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
} from '@nestjs/swagger';
import { type JwtPayload, CurrentUser, JwtAuthGuard, RolesGuard, Roles } from '@modules/auth';
import { CreateLeadCommand } from '../../application/commands/create-lead/create-lead.command';
import { type CreateLeadResult } from '../../application/commands/create-lead/create-lead.handler';
import { DeleteLeadCommand } from '../../application/commands/delete-lead/delete-lead.command';
import { UpdateLeadStatusCommand } from '../../application/commands/update-lead-status/update-lead-status.command';
import { GetLeadStatsQuery } from '../../application/queries/get-lead-stats/get-lead-stats.query';
import { GetLeadsByAgentQuery } from '../../application/queries/get-leads-by-agent/get-leads-by-agent.query';
import { type LeadReadDto } from '../../domain/repositories/lead-read.dto';
import { type LeadStatsData, type PaginatedResult } from '../../domain/repositories/lead.repository';
import { CreateLeadDto } from '../dto/create-lead.dto';
import { ListLeadsDto } from '../dto/list-leads.dto';
import { UpdateLeadStatusDto } from '../dto/update-lead-status.dto';

@ApiTags('leads')
@ApiBearerAuth('JWT')
@Controller('leads')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('AGENT')
export class LeadsController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  @ApiOperation({ summary: 'Tạo lead mới' })
  @ApiResponse({ status: 201, description: 'Lead đã được tạo thành công' })
  @ApiResponse({ status: 400, description: 'Lỗi validation' })
  @ApiResponse({ status: 401, description: 'Chưa xác thực' })
  @ApiResponse({ status: 403, description: 'Không có quyền' })
  @Post()
  async createLead(
    @Body() dto: CreateLeadDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<CreateLeadResult> {
    return this.commandBus.execute(
      new CreateLeadCommand(
        user.sub,
        dto.name,
        dto.phone,
        dto.email ?? null,
        dto.source,
        dto.score ?? null,
        dto.notes ?? null,
      ),
    );
  }

  @ApiOperation({ summary: 'Danh sách lead của agent' })
  @ApiResponse({ status: 200, description: 'Danh sách lead phân trang' })
  @Get()
  async getLeads(
    @Query() dto: ListLeadsDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<PaginatedResult<LeadReadDto>> {
    return this.queryBus.execute(
      new GetLeadsByAgentQuery(
        user.sub,
        dto.status ?? null,
        dto.page ?? 1,
        dto.limit ?? 20,
      ),
    );
  }

  @ApiOperation({ summary: 'Thống kê lead của agent' })
  @ApiResponse({ status: 200, description: 'Thống kê lead' })
  @Get('stats')
  async getStats(
    @CurrentUser() user: JwtPayload,
  ): Promise<LeadStatsData> {
    return this.queryBus.execute(
      new GetLeadStatsQuery(user.sub),
    );
  }

  @ApiOperation({ summary: 'Cập nhật trạng thái lead' })
  @ApiParam({ name: 'id', description: 'Lead ID' })
  @ApiResponse({ status: 200, description: 'Trạng thái đã được cập nhật' })
  @ApiResponse({ status: 400, description: 'Chuyển trạng thái không hợp lệ' })
  @ApiResponse({ status: 403, description: 'Không có quyền' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy lead' })
  @Patch(':id/status')
  async updateStatus(
    @Param('id') id: string,
    @Body() dto: UpdateLeadStatusDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<{ updated: boolean }> {
    await this.commandBus.execute(
      new UpdateLeadStatusCommand(id, user.sub, dto.status),
    );
    return { updated: true };
  }

  @ApiOperation({ summary: 'Xóa lead' })
  @ApiParam({ name: 'id', description: 'Lead ID' })
  @ApiResponse({ status: 200, description: 'Lead đã được xóa' })
  @ApiResponse({ status: 403, description: 'Không có quyền' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy lead' })
  @Delete(':id')
  async deleteLead(
    @Param('id') id: string,
    @CurrentUser() user: JwtPayload,
  ): Promise<{ deleted: boolean }> {
    await this.commandBus.execute(new DeleteLeadCommand(id, user.sub));
    return { deleted: true };
  }
}
