import { Body, Controller, Get, Param, 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 { CurrentUser } from '../../common/decorators/current-user.decorator';
import type { AuthenticatedUser } from '../../common/decorators/current-user.decorator';
import { PlanAssignmentService } from './plan-assignment.service';
import {
  CreateAssignmentRequestDto,
  CreateAssignmentResponseDto,
  ListAssignmentsResponseDto,
  AssignmentDetailResponseDto,
} from './dto/plan-assignment.dto';

/**
 * 批次分配端点 —— 门诊经理专用。
 *
 * ⛔ **刻意不改** `POST /plans/:id/assign` 与 `/plans/:id/recycle`:
 *   前者维持 PLAN_ASSIGN(认领语义,staff 也有,前端虽撤了入口但后端保留 —— T12/T16),
 *   后者维持 PLAN_RECYCLE(退回是客服路径)。
 *   把批次能力塞进那两个端点会让"客服自助"与"主管派单"两条路的权限纠缠在一起。
 *
 * 路由挂在 `plans/assignments` 而不是顶层 `plan-assignments`:
 *   它是 plan 的从属资源,跟 `plans/:id/executions` 同一层级心智。
 */
@ApiTags('plan-assignments')
@ApiBearerAuth('accessToken')
@Controller('plans/assignments')
export class AssignmentController {
  constructor(private readonly assignments: PlanAssignmentService) {}

  @Post()
  @RequirePermission(Permission.PLAN_DISPATCH)
  @ZodResponse({ status: 201, type: CreateAssignmentResponseDto })
  @ApiOperation({
    summary: '确认分配 —— 主管在确认单上点确认时调用(整条生产线唯一的写动作)',
    description:
      '幂等:requestId 由服务端在生成确认单时铸造,重复提交返回同一批次 + duplicate:true。' +
      '部分计划在确认期间被他人认领时其余照落,逐条在 skipped 里说明原因;一条都落不上则不建批次。',
  })
  async create(
    @TenantScope() scope: TenantScopeContext,
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: CreateAssignmentRequestDto,
  ) {
    return this.assignments.create(
      scope,
      { userId: user.sub, permissions: user.permissions },
      dto,
    );
  }

  @Get()
  @RequirePermission(Permission.PLAN_DISPATCH)
  @ZodResponse({ status: 200, type: ListAssignmentsResponseDto })
  @ApiOperation({ summary: '我分的那些批 —— 批次列表 + 每批汇总(分了/在手/已退回/涉及几人)' })
  async list(
    @TenantScope() scope: TenantScopeContext,
    @CurrentUser() user: AuthenticatedUser,
    @Query('mine') mine?: string,
  ) {
    // mine=1 → 只看自己发起的。默认看本 scope 全部(leader 之间要能互相看见,
    // 否则"这个诊所这周分了多少"永远拼不出来)
    return this.assignments.list(scope, mine === '1' ? user.sub : undefined);
  }

  @Get(':id')
  @RequirePermission(Permission.PLAN_DISPATCH)
  @ZodResponse({ status: 200, type: AssignmentDetailResponseDto })
  @ApiOperation({ summary: '单批全貌 —— 按客服拆 + 退回原因分布' })
  async detail(@TenantScope() scope: TenantScopeContext, @Param('id') id: string) {
    return this.assignments.detail(scope, id);
  }
}
