import { ForbiddenException, Inject } from '@nestjs/common';
import { type ICommandHandler, CommandHandler } from '@nestjs/cqrs';
import { NotFoundException } from '@modules/shared';
import {
  PROJECT_REPOSITORY,
  type IProjectRepository,
} from '../../../domain/repositories/project-development.repository';
import { UpdateProjectCommand } from './update-project.command';

@CommandHandler(UpdateProjectCommand)
export class UpdateProjectHandler implements ICommandHandler<UpdateProjectCommand> {
  constructor(
    @Inject(PROJECT_REPOSITORY)
    private readonly repo: IProjectRepository,
  ) {}

  async execute(cmd: UpdateProjectCommand): Promise<{ id: string }> {
    const entity = await this.repo.findById(cmd.id);
    if (!entity) {
      throw new NotFoundException('Dự án', cmd.id);
    }

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

    entity.updateDetails({
      ...(cmd.name !== undefined && { name: cmd.name }),
      ...(cmd.developer !== undefined && { developer: cmd.developer }),
      ...(cmd.developerLogo !== undefined && { developerLogo: cmd.developerLogo }),
      ...(cmd.totalUnits !== undefined && { totalUnits: cmd.totalUnits }),
      ...(cmd.completedUnits !== undefined && { completedUnits: cmd.completedUnits }),
      ...(cmd.status !== undefined && { status: cmd.status }),
      ...(cmd.description !== undefined && { description: cmd.description }),
      ...(cmd.amenities !== undefined && { amenities: cmd.amenities }),
      ...(cmd.masterPlanUrl !== undefined && { masterPlanUrl: cmd.masterPlanUrl }),
      ...(cmd.minPrice !== undefined && { minPrice: cmd.minPrice }),
      ...(cmd.maxPrice !== undefined && { maxPrice: cmd.maxPrice }),
      ...(cmd.pricePerM2Range !== undefined && { pricePerM2Range: cmd.pricePerM2Range }),
      ...(cmd.totalArea !== undefined && { totalArea: cmd.totalArea }),
      ...(cmd.buildingCount !== undefined && { buildingCount: cmd.buildingCount }),
      ...(cmd.floorCount !== undefined && { floorCount: cmd.floorCount }),
      ...(cmd.unitTypes !== undefined && { unitTypes: cmd.unitTypes }),
      ...(cmd.media !== undefined && { media: cmd.media }),
      ...(cmd.documents !== undefined && { documents: cmd.documents }),
      ...(cmd.tags !== undefined && { tags: cmd.tags }),
      ...(cmd.suitableFor !== undefined && { suitableFor: cmd.suitableFor }),
      ...(cmd.whyThisLocation !== undefined && { whyThisLocation: cmd.whyThisLocation }),
      ...(cmd.isVerified !== undefined && { isVerified: cmd.isVerified }),
      ...(cmd.startDate !== undefined && { startDate: cmd.startDate }),
      ...(cmd.completionDate !== undefined && { completionDate: cmd.completionDate }),
      ...(cmd.ownerId !== undefined && { ownerId: cmd.ownerId }),
    });

    await this.repo.update(entity);
    return { id: entity.id };
  }
}
