import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseUUIDPipe,
  Post,
} from '@nestjs/common';
import { PermissionDelegationService } from '@common/services/permission-delegation.service';
import { RequirePermissions } from '@common/decorators/permissions.decorator';
import { CurrentUser } from '@common/decorators/current-user.decorator';
import { Auditable, Sensitive } from '@core/observability/audit/decorators/auditable.decorator';
import { IsISO8601, IsOptional, IsString, IsUUID } from 'class-validator';

class CreateDelegationRequestDto {
  @IsUUID()
  toUserId!: string;

  @IsOptional()
  @IsString()
  resource?: string;

  @IsISO8601()
  validFrom!: string;

  @IsISO8601()
  validTo!: string;

  @IsString()
  reason!: string;

  @IsOptional()
  @IsUUID()
  organizationId?: string;
}

/**
 * IAM 权限委托 REST API（规则 §5.3.14）
 *
 * 鉴权策略：
 * - mine 列表：所有登录用户可查看自己作为发起人/受托人的委托
 * - 创建 / 撤销：delegation:manage 或 system:admin（system:admin 可代他人发起）
 *
 * 简化约定：本接口的 fromUserId 永远是当前调用者本人，不允许"system:admin 代他人发起"
 * 走此通道。代他人发起需要专用 admin 接口（待后续视需求添加）。
 */
@Controller('iam/delegations')
export class DelegationsController {
  constructor(private readonly service: PermissionDelegationService) {}

  // /mine 只返回当前用户作为发起人/受托人的委托，service 内已用 userId 限定。
  // 不挂 @RequirePermissions：被委托的普通员工应能看自己收到的委托。
  @Get('mine')
  async listMine(@CurrentUser('userId') userId: string) {
    return this.service.listRelatedToUser(userId);
  }

  @Post()
  @RequirePermissions('delegation:manage')
  @Auditable()
  @Sensitive()
  async create(
    @Body() body: CreateDelegationRequestDto,
    @CurrentUser('userId') actorId: string,
  ) {
    return this.service.create({
      fromUserId: actorId,
      toUserId: body.toUserId,
      resource: body.resource,
      validFrom: new Date(body.validFrom),
      validTo: new Date(body.validTo),
      reason: body.reason,
      organizationId: body.organizationId,
      createdById: actorId,
    });
  }

  @Delete(':id')
  @RequirePermissions('delegation:manage')
  @Auditable()
  @Sensitive()
  async revoke(
    @Param('id', ParseUUIDPipe) id: string,
    @CurrentUser('userId') actorId: string,
  ) {
    return this.service.revoke(id, actorId);
  }
}
