import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard, CurrentUser } from '@modules/auth';
import { EndpointRateLimit, EndpointRateLimitGuard, NotFoundException } from '@modules/shared';
import { CreateTransferListingCommand } from '../../application/commands/create-transfer-listing/create-transfer-listing.command';
import { DeleteTransferListingCommand } from '../../application/commands/delete-transfer-listing/delete-transfer-listing.command';
import { EstimateFromPhotosCommand } from '../../application/commands/estimate-from-photos/estimate-from-photos.command';
import { EstimateTransferPricesCommand } from '../../application/commands/estimate-transfer-prices/estimate-transfer-prices.command';
import { UpdateTransferListingCommand } from '../../application/commands/update-transfer-listing/update-transfer-listing.command';
import { GetTransferListingQuery } from '../../application/queries/get-transfer-listing/get-transfer-listing.query';
import { ListTransferListingsQuery } from '../../application/queries/list-transfer-listings/list-transfer-listings.query';
import { TransferStatsQuery } from '../../application/queries/transfer-stats/transfer-stats.query';
import { CreateTransferListingDto } from '../dto/create-transfer-listing.dto';
import { EstimateFromPhotosDto } from '../dto/estimate-from-photos.dto';
import { EstimateTransferPricesDto } from '../dto/estimate-transfer-prices.dto';
import { SearchTransferListingsDto } from '../dto/search-transfer-listings.dto';
import { UpdateTransferListingDto } from '../dto/update-transfer-listing.dto';

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

  // ── Public endpoints ──────────────────────────────────────────────

  @ApiOperation({ summary: 'Danh sách sang nhượng', description: 'Tìm kiếm và lọc tin sang nhượng' })
  @ApiResponse({ status: 200, description: 'Danh sách tin sang nhượng phân trang' })
  @Get('listings')
  async listListings(@Query() dto: SearchTransferListingsDto) {
    return this.queryBus.execute(
      new ListTransferListingsQuery(
        dto.q,
        dto.category,
        dto.status,
        dto.district,
        dto.city,
        dto.minPrice,
        dto.maxPrice,
        undefined, // sellerId — only used for "my listings" queries
        dto.page ?? 1,
        dto.limit ?? 20,
      ),
    );
  }

  @ApiOperation({ summary: 'Chi tiết tin sang nhượng', description: 'Xem chi tiết tin sang nhượng theo ID' })
  @ApiResponse({ status: 200, description: 'Thông tin chi tiết tin sang nhượng' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy tin sang nhượng' })
  @Get('listings/:id')
  async getListing(@Param('id') id: string) {
    const result = await this.queryBus.execute(new GetTransferListingQuery(id));
    if (!result) {
      throw new NotFoundException('Transfer listing', id);
    }
    return result;
  }

  @ApiOperation({ summary: 'Thống kê sang nhượng', description: 'Tổng quan thống kê tin sang nhượng' })
  @ApiResponse({ status: 200, description: 'Dữ liệu thống kê' })
  @Get('stats')
  async getStats() {
    return this.queryBus.execute(new TransferStatsQuery());
  }

  @ApiOperation({ summary: 'Ước tính giá AI', description: 'Ước tính giá trị nội thất/thiết bị dựa trên khấu hao, thương hiệu và tình trạng' })
  @ApiResponse({ status: 200, description: 'Kết quả ước tính giá' })
  @Post('estimate')
  async estimatePrices(@Body() dto: EstimateTransferPricesDto) {
    return this.commandBus.execute(
      new EstimateTransferPricesCommand(dto.items),
    );
  }

  @ApiOperation({
    summary: 'Ước tính giá từ ảnh (AI Vision)',
    description: 'Sử dụng Claude Vision để đánh giá tình trạng nội thất từ ảnh, kết hợp với công cụ định giá rule-based',
  })
  @ApiResponse({ status: 200, description: 'Kết quả đánh giá tình trạng và ước tính giá' })
  @ApiResponse({ status: 429, description: 'Rate limit exceeded' })
  @EndpointRateLimit({ limit: 5, windowSeconds: 60, keyStrategy: 'ip' })
  @UseGuards(EndpointRateLimitGuard)
  @Post('estimate-from-photos')
  async estimateFromPhotos(@Body() dto: EstimateFromPhotosDto) {
    return this.commandBus.execute(
      new EstimateFromPhotosCommand(dto.items),
    );
  }

  // ── Authenticated endpoints ───────────────────────────────────────

  @ApiOperation({ summary: 'Tạo tin sang nhượng', description: 'Đăng tin sang nhượng mới' })
  @ApiResponse({ status: 201, description: 'Tin sang nhượng đã tạo' })
  @ApiResponse({ status: 400, description: 'Validation error' })
  @ApiResponse({ status: 401, description: 'Chưa xác thực' })
  @ApiBearerAuth('JWT')
  @UseGuards(JwtAuthGuard)
  @Post('listings')
  async createListing(
    @CurrentUser() user: { sub: string },
    @Body() dto: CreateTransferListingDto,
  ) {
    return this.commandBus.execute(
      new CreateTransferListingCommand(
        user.sub,
        dto.category,
        dto.title,
        dto.description ?? null,
        dto.address,
        dto.ward ?? null,
        dto.district,
        dto.city,
        dto.latitude,
        dto.longitude,
        BigInt(Math.round(dto.askingPriceVND)),
        dto.pricingSource ?? 'MANUAL',
        dto.isNegotiable ?? true,
        dto.areaM2 ?? null,
        dto.monthlyRentVND ? BigInt(Math.round(dto.monthlyRentVND)) : null,
        dto.depositMonths ?? null,
        dto.remainingLeaseMo ?? null,
        dto.businessType ?? null,
        dto.footTraffic ?? null,
        dto.contactPhone ?? null,
        dto.contactName ?? null,
        (dto.items ?? []).map((item) => ({
          name: item.name,
          brand: item.brand,
          modelName: item.modelName,
          category: item.category,
          condition: item.condition,
          purchaseYear: item.purchaseYear,
          originalPriceVND: item.originalPriceVND != null ? BigInt(Math.round(item.originalPriceVND)) : undefined,
          askingPriceVND: BigInt(Math.round(item.askingPriceVND)),
          quantity: item.quantity,
          dimensions: item.dimensions,
          notes: item.notes,
        })),
      ),
    );
  }

  @ApiOperation({ summary: 'Cập nhật tin sang nhượng', description: 'Cập nhật thông tin tin sang nhượng' })
  @ApiResponse({ status: 200, description: 'Tin sang nhượng đã cập nhật' })
  @ApiResponse({ status: 401, description: 'Chưa xác thực' })
  @ApiResponse({ status: 403, description: 'Không có quyền' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy tài nguyên' })
  @ApiBearerAuth('JWT')
  @UseGuards(JwtAuthGuard)
  @Patch('listings/:id')
  async updateListing(
    @Param('id') id: string,
    @Body() dto: UpdateTransferListingDto,
  ) {
    return this.commandBus.execute(
      new UpdateTransferListingCommand(
        id,
        dto.title,
        dto.description,
        dto.status,
        dto.askingPriceVND ? BigInt(Math.round(dto.askingPriceVND)) : undefined,
        dto.isNegotiable,
        dto.areaM2,
        dto.monthlyRentVND !== undefined ? BigInt(Math.round(dto.monthlyRentVND)) : undefined,
        dto.depositMonths,
        dto.remainingLeaseMo,
        dto.businessType,
        dto.footTraffic,
        dto.contactPhone,
        dto.contactName,
        dto.media,
      ),
    );
  }

  @ApiOperation({ summary: 'Xoá tin sang nhượng', description: 'Xoá (soft-delete) tin sang nhượng của bạn' })
  @ApiResponse({ status: 200, description: 'Tin sang nhượng đã xoá' })
  @ApiResponse({ status: 403, description: 'Không có quyền xoá tin này' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy tin sang nhượng' })
  @ApiBearerAuth('JWT')
  @UseGuards(JwtAuthGuard)
  @Delete('listings/:id')
  async deleteListing(
    @Param('id') id: string,
    @CurrentUser() user: { sub: string },
  ) {
    return this.commandBus.execute(
      new DeleteTransferListingCommand(id, user.sub),
    );
  }
}
