import {
  Body,
  Controller,
  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, Roles, JwtAuthGuard, RolesGuard } from '@modules/auth';
import { CreateInquiryCommand } from '../../application/commands/create-inquiry/create-inquiry.command';
import { type CreateInquiryResult } from '../../application/commands/create-inquiry/create-inquiry.handler';
import { MarkInquiryReadCommand } from '../../application/commands/mark-inquiry-read/mark-inquiry-read.command';
import { GetInquiriesByAgentQuery } from '../../application/queries/get-inquiries-by-agent/get-inquiries-by-agent.query';
import { GetInquiriesByListingQuery } from '../../application/queries/get-inquiries-by-listing/get-inquiries-by-listing.query';
import { type InquiryReadDto } from '../../domain/repositories/inquiry-read.dto';
import { type PaginatedResult } from '../../domain/repositories/inquiry.repository';
import { CreateInquiryDto } from '../dto/create-inquiry.dto';
import { ListInquiriesDto } from '../dto/list-inquiries.dto';

@ApiTags('inquiries')
@Controller('inquiries')
export class InquiriesController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Create an inquiry for a listing' })
  @ApiResponse({ status: 201, description: 'Inquiry created successfully' })
  @ApiResponse({ status: 400, description: 'Validation error' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Listing not found' })
  @UseGuards(JwtAuthGuard)
  @Post()
  async createInquiry(
    @Body() dto: CreateInquiryDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<CreateInquiryResult> {
    return this.commandBus.execute(
      new CreateInquiryCommand(
        user.sub,
        dto.listingId,
        dto.message,
        dto.phone ?? null,
      ),
    );
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'List inquiries by listing' })
  @ApiParam({ name: 'listingId', description: 'Listing ID' })
  @ApiResponse({ status: 200, description: 'Paginated list of inquiries' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @UseGuards(JwtAuthGuard)
  @Get('listing/:listingId')
  async getByListing(
    @Param('listingId') listingId: string,
    @Query() dto: ListInquiriesDto,
  ): Promise<PaginatedResult<InquiryReadDto>> {
    return this.queryBus.execute(
      new GetInquiriesByListingQuery(
        listingId,
        dto.page ?? 1,
        dto.limit ?? 20,
      ),
    );
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'List inquiries for current agent' })
  @ApiResponse({ status: 200, description: 'Paginated list of inquiries for agent' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden — not an agent' })
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles('AGENT')
  @Get('agent/me')
  async getMyInquiries(
    @CurrentUser() user: JwtPayload,
    @Query() dto: ListInquiriesDto,
  ): Promise<PaginatedResult<InquiryReadDto>> {
    return this.queryBus.execute(
      new GetInquiriesByAgentQuery(
        user.sub,
        dto.page ?? 1,
        dto.limit ?? 20,
      ),
    );
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Mark inquiry as read' })
  @ApiParam({ name: 'id', description: 'Inquiry ID' })
  @ApiResponse({ status: 200, description: 'Inquiry marked as read' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden — not the listing agent' })
  @ApiResponse({ status: 404, description: 'Inquiry not found' })
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles('AGENT')
  @Patch(':id/read')
  async markAsRead(
    @Param('id') id: string,
    @CurrentUser() user: JwtPayload,
  ): Promise<{ success: boolean }> {
    await this.commandBus.execute(
      new MarkInquiryReadCommand(id, user.sub),
    );
    return { success: true };
  }
}
