import { ForbiddenException, Inject } from '@nestjs/common';
import { type ICommandHandler, CommandHandler } from '@nestjs/cqrs';
import { NotFoundException } from '@modules/shared';
import {
  INDUSTRIAL_PARK_REPOSITORY,
  type IIndustrialParkRepository,
} from '../../../domain/repositories/industrial-park.repository';
import { UpdateIndustrialParkCommand } from './update-industrial-park.command';

@CommandHandler(UpdateIndustrialParkCommand)
export class UpdateIndustrialParkHandler implements ICommandHandler<UpdateIndustrialParkCommand> {
  constructor(
    @Inject(INDUSTRIAL_PARK_REPOSITORY)
    private readonly repo: IIndustrialParkRepository,
  ) {}

  async execute(cmd: UpdateIndustrialParkCommand): Promise<void> {
    const entity = await this.repo.findById(cmd.id);
    if (!entity) {
      throw new NotFoundException('Industrial park', cmd.id);
    }

    // Authorisation: ADMIN may edit anything. PARK_OPERATOR may edit only
    // parks they own. Reassigning `ownerId` is admin-only.
    if (cmd.requesterRole !== 'ADMIN') {
      if (cmd.requesterRole !== 'PARK_OPERATOR' || entity.ownerId !== cmd.requesterUserId) {
        throw new ForbiddenException('Bạn không có quyền chỉnh sửa KCN này');
      }
      if (cmd.ownerId !== undefined) {
        throw new ForbiddenException('Chỉ admin có thể chuyển quyền sở hữu KCN');
      }
    }

    entity.updateDetails({
      name: cmd.name,
      nameEn: cmd.nameEn,
      developer: cmd.developer,
      operator: cmd.operator,
      status: cmd.status,
      occupancyRate: cmd.occupancyRate,
      remainingAreaHa: cmd.remainingAreaHa,
      tenantCount: cmd.tenantCount,
      landRentUsdM2Year: cmd.landRentUsdM2Year,
      rbfRentUsdM2Month: cmd.rbfRentUsdM2Month,
      rbwRentUsdM2Month: cmd.rbwRentUsdM2Month,
      managementFeeUsd: cmd.managementFeeUsd,
      infrastructure: cmd.infrastructure,
      connectivity: cmd.connectivity,
      incentives: cmd.incentives,
      targetIndustries: cmd.targetIndustries,
      description: cmd.description,
      descriptionEn: cmd.descriptionEn,
      isVerified: cmd.isVerified,
      ...(cmd.ownerId !== undefined && { ownerId: cmd.ownerId }),
    });

    await this.repo.update(entity);
  }
}
