import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { type CommandBus, type QueryBus } from '@nestjs/cqrs';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { UserRole } from '@prisma/client';
import { JwtAuthGuard, Roles, RolesGuard } from '@modules/auth';
import { NotFoundException } from '@modules/shared';
import { CreateIndustrialParkCommand } from '../../application/commands/create-industrial-park/create-industrial-park.command';
import { UpdateIndustrialParkCommand } from '../../application/commands/update-industrial-park/update-industrial-park.command';
import { CompareIndustrialParksQuery } from '../../application/queries/compare-industrial-parks/compare-industrial-parks.query';
import { GetIndustrialParkQuery } from '../../application/queries/get-industrial-park/get-industrial-park.query';
import { IndustrialMarketQuery } from '../../application/queries/industrial-market/industrial-market.query';
import { IndustrialParkStatsQuery } from '../../application/queries/industrial-park-stats/industrial-park-stats.query';
import { ListIndustrialParksQuery } from '../../application/queries/list-industrial-parks/list-industrial-parks.query';
import { type CompareIndustrialParksDto } from '../dto/compare-industrial-parks.dto';
import { type CreateIndustrialParkDto } from '../dto/create-industrial-park.dto';
import { type SearchIndustrialParksDto } from '../dto/search-industrial-parks.dto';
import { type UpdateIndustrialParkDto } from '../dto/update-industrial-park.dto';

@ApiTags('industrial-parks')
@Controller('industrial')
export class IndustrialParksController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

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

  @ApiOperation({ summary: 'Danh sách KCN', description: 'Tìm kiếm và lọc khu công nghiệp' })
  @ApiResponse({ status: 200, description: 'Danh sách KCN phân trang' })
  @Get('parks')
  async listParks(@Query() dto: SearchIndustrialParksDto) {
    return this.queryBus.execute(
      new ListIndustrialParksQuery(
        dto.q,
        dto.province,
        dto.region,
        dto.status,
        dto.minAreaHa,
        dto.maxRentUsdM2,
        dto.targetIndustry,
        dto.page ?? 1,
        dto.limit ?? 20,
      ),
    );
  }

  @ApiOperation({ summary: 'Chi tiết KCN', description: 'Xem chi tiết KCN theo slug hoặc ID' })
  @ApiResponse({ status: 200, description: 'Thông tin chi tiết KCN' })
  @ApiResponse({ status: 404, description: 'Không tìm thấy KCN' })
  @Get('parks/:slugOrId')
  async getPark(@Param('slugOrId') slugOrId: string) {
    const result = await this.queryBus.execute(new GetIndustrialParkQuery(slugOrId));
    if (!result) {
      throw new NotFoundException('Industrial park', slugOrId);
    }
    return result;
  }

  @ApiOperation({ summary: 'So sánh KCN', description: 'So sánh 2-5 KCN' })
  @ApiResponse({ status: 200, description: 'Dữ liệu so sánh KCN' })
  @Post('parks/compare')
  async compareParks(@Body() dto: CompareIndustrialParksDto) {
    return this.queryBus.execute(new CompareIndustrialParksQuery(dto.ids));
  }

  @ApiOperation({ summary: 'Thống kê KCN', description: 'Tổng quan thống kê tất cả KCN' })
  @ApiResponse({ status: 200, description: 'Dữ liệu thống kê' })
  @Get('parks/stats')
  async getStats() {
    return this.queryBus.execute(new IndustrialParkStatsQuery());
  }

  @ApiOperation({ summary: 'Thị trường KCN', description: 'Dữ liệu thị trường BĐS công nghiệp' })
  @ApiResponse({ status: 200, description: 'Dữ liệu thị trường' })
  @Get('market')
  async getMarket() {
    return this.queryBus.execute(new IndustrialMarketQuery());
  }

  // ── Admin endpoints ───────────────────────────────────────────────

  @ApiOperation({ summary: 'Tạo KCN (admin)', description: 'Tạo mới khu công nghiệp' })
  @ApiResponse({ status: 201, description: 'KCN đã tạo' })
  @ApiBearerAuth('JWT')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Post('parks')
  async createPark(@Body() dto: CreateIndustrialParkDto) {
    return this.commandBus.execute(
      new CreateIndustrialParkCommand(
        dto.name,
        dto.nameEn ?? null,
        dto.slug,
        dto.developer,
        dto.operator ?? null,
        dto.status,
        dto.latitude,
        dto.longitude,
        dto.address,
        dto.district,
        dto.province,
        dto.region,
        dto.totalAreaHa,
        dto.leasableAreaHa,
        dto.occupancyRate,
        dto.remainingAreaHa,
        dto.tenantCount ?? 0,
        dto.establishedYear ?? null,
        dto.landRentUsdM2Year ?? null,
        dto.rbfRentUsdM2Month ?? null,
        dto.rbwRentUsdM2Month ?? null,
        dto.managementFeeUsd ?? null,
        dto.infrastructure ?? null,
        dto.connectivity ?? null,
        dto.incentives ?? null,
        dto.targetIndustries,
        dto.description ?? null,
        dto.descriptionEn ?? null,
      ),
    );
  }

  @ApiOperation({ summary: 'Cập nhật KCN (admin)', description: 'Cập nhật thông tin KCN' })
  @ApiResponse({ status: 200, description: 'KCN đã cập nhật' })
  @ApiBearerAuth('JWT')
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(UserRole.ADMIN)
  @Patch('parks/:id')
  async updatePark(@Param('id') id: string, @Body() dto: UpdateIndustrialParkDto) {
    return this.commandBus.execute(
      new UpdateIndustrialParkCommand(
        id,
        dto.name,
        dto.nameEn,
        dto.developer,
        dto.operator,
        dto.status,
        dto.occupancyRate,
        dto.remainingAreaHa,
        dto.tenantCount,
        dto.landRentUsdM2Year,
        dto.rbfRentUsdM2Month,
        dto.rbwRentUsdM2Month,
        dto.managementFeeUsd,
        dto.infrastructure,
        dto.connectivity,
        dto.incentives,
        dto.targetIndustries,
        dto.description,
        dto.descriptionEn,
        dto.isVerified,
      ),
    );
  }
}
