import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ZodResponse } from 'nestjs-zod';
import { Permission } from '@pac/types';
import { RequirePermission } from '../../common/decorators/permissions.decorator';
import { TenantScope } from '../../common/decorators/tenant-scope.decorator';
import type { TenantScopeContext } from '../../common/decorators/tenant-scope.decorator';
import { resolveClinicId } from '../../common/decorators/resolve-clinic-id';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import type { AuthenticatedUser } from '../../common/decorators/current-user.decorator';
import { PlanRearrangeService } from './plan-rearrange.service';
import { RearrangeDraftDto, RearrangeSubmitRequestDto, RearrangeSubmitResponseDto } from './dto/plan-rearrange.dto';

/**
 * 主管调整端点 —— 调整各客服此刻在手的单。
 *
 * ⚠️ **本控制器必须注册在 `PlanController` 之前**(见 plan.module 的 controllers 数组)。
 *   `PlanController` 挂在 `plans` 上且有一个裸 `@Get(':id')`,Nest 按注册顺序匹配 ——
 *   排在它后面的话 `GET /plans/rearrange` 这类单段路径会被当成 planId='rearrange',
 *   报出来是 Prisma 的 uuid 解析错,看不出是路由问题(AssignmentController 实测踩过)。
 *
 * ⛔ 刻意**不复用** `plans/assignments` 前缀:调整不建批次、不属于任何一次分配,
 *   挂进去会让"这是分配的一部分"这个错觉在路由上就成立。
 */
@ApiTags('plan-rearrange')
@ApiBearerAuth('accessToken')
@Controller('plans/rearrange')
export class RearrangeController {
  constructor(private readonly rearrange: PlanRearrangeService) {}

  @Get('draft')
  @RequirePermission(Permission.PLAN_DISPATCH)
  @ZodResponse({ status: 200, type: RearrangeDraftDto })
  @ApiOperation({
    summary: '取一版可编辑的在手快照 —— 不传 agents = 全景(全队),传了 = 只调这几位',
    description:
      '⛔ 不写任何数据。`operationId` 由服务端铸造,提交时原样回传做幂等键。' +
      '人员集合走客服名册(与分配、团队状态同源)—— 名册外的人手上的单本期不管。',
  })
  async draft(
    @TenantScope() scope: TenantScopeContext,
    @Query('clinicId') clinicId?: string,
    /// 逗号分隔的客服 userId;不传 = 全队
    @Query('agents') agents?: string,
  ) {
    return this.rearrange.draft(
      scope,
      // 🔴 越权闸:这条路会吐**患者姓名**,收了 clinicId 就必须过闸(纪律见 assignment.controller)
      resolveClinicId(scope, clinicId),
      agents
        ? agents
            .split(',')
            .map((s) => s.trim())
            .filter(Boolean)
        : undefined,
    );
  }

  @Post()
  @RequirePermission(Permission.PLAN_DISPATCH)
  @ZodResponse({ status: 200, type: RearrangeSubmitResponseDto })
  @ApiOperation({
    summary: '确认调整 —— 主管在调整单上点确认时调用(这条路唯一的写动作)',
    description:
      '幂等:同一个 operationId 重复提交返回 duplicate:true,一个字都不写。' +
      '**逐条落**,落不上的(客服刚打完 / 已退回 / 被重算取代)逐条在 skipped 里说明;' +
      '⛔ 不是"数量对不上整体拒绝"。',
  })
  async submit(
    @TenantScope() scope: TenantScopeContext,
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: RearrangeSubmitRequestDto,
  ) {
    return this.rearrange.submit(scope, { userId: user.sub, permissions: user.permissions }, dto);
  }
}
