'use client';

import type {
  AgentWorkloadResponse,
  AnchorModeValue,
  CreateAssignmentRequest,
  CreateAssignmentResponse,
  ListAgentsResponse,
  ListAssignmentsResponse,
  AssignmentDetailResponse,
  AssignmentProposal,
  RefillProposalRequest,
  RevokeAssignmentResponse,
  SetAssignmentBenefitResponse,
} from '@pac/types';
import { api } from '@/lib/api-client';

/**
 * 中间表的一行 —— 字段与确认单的患者行**逐个对齐**(服务端同一个 `patientsOf`)。
 * ⛔ 别在这里加确认单没有的字段:两张表看着不一样,主管会以为是两批人。
 */
export interface CohortPatientRow {
  planId: string;
  patientId: string;
  patientName: string | null;
  medicalRecordNumber: string | null;
  gender: string | null;
  age: number | null;
  /** 主治 / 偏好医生(病历里出现频次最高的) */
  attendingDoctor: string | null;
  /** 上次到诊当天那份病历的医生 */
  lastVisitDoctor: string | null;
  /** 专属客服(有就显示名字)—— 主管一眼看出这批里有多少本来就是谁的客户 */
  dedicatedTo: string | null;
  dedicatedToName: string | null;
  /** 之前被分过的人又出现了 */
  repeated: boolean;
  priorityScore: number;
}

export interface CohortPage {
  clinicId: string;
  total: number;
  page: number;
  pageSize: number;
  items: CohortPatientRow[];
}

/**
 * 批次分配 API。
 *
 * ⚠️ 路径都在 `plans/assignments` 之下 —— **别写成 `/plans/agents`**:
 * 那个路径归 PlanController,会被它的裸 `@Get(':id')` 当成 planId,
 * 报出来是 Prisma 的 uuid 解析错,完全看不出是路由撞了(实测踩过)。
 */
export const assignmentsApi = {
  /**
   * 确认分配 —— **整条生产线唯一的写动作**。
   * ⚠️ `requestId` 必须原样回传服务端在出确认单时铸造的那个(幂等键);
   * 前端自己生成挡不住 SSE 重连与重试。
   */
  create: (body: CreateAssignmentRequest) =>
    api.post<CreateAssignmentResponse>('/pac/v1/plans/assignments', body),

  /**
   * 批次列表。
   * ⚠️ `before` 是**游标**(上一页最后一条的 createdAt),⛔ 不是 offset ——
   *   批次一直在新增,offset 翻页会重复或漏行。
   */
  list: (opts?: { mine?: boolean; limit?: number; before?: string }) => {
    const q = new URLSearchParams();
    if (opts?.mine) q.set('mine', '1');
    if (opts?.limit) q.set('limit', String(opts.limit));
    if (opts?.before) q.set('before', opts.before);
    const s = q.toString();
    return api.get<ListAssignmentsResponse>(`/pac/v1/plans/assignments${s ? `?${s}` : ''}`);
  },

  /**
   * 团队现在什么状态 —— 主管工作台右栏。
   * ⚠️ 只有「当前在手」是此刻的,超期/完成/退回/没动都在 `days` 这个窗口里;
   *   响应里的 `note` 已经写好这句,⛔ 界面照抄别自己另写一版。
   */
  workload: (clinicId: string, days: number) =>
    api.get<AgentWorkloadResponse>(
      `/pac/v1/plans/assignments/workload?clinicId=${encodeURIComponent(clinicId)}&days=${days}`,
    ),

  detail: (id: string) =>
    api.get<AssignmentDetailResponse>(`/pac/v1/plans/assignments/${encodeURIComponent(id)}`),

  /** 在岗客服名册 + 在手负载(一个端点,不拆两个 —— 拆开必然口径漂移) */
  /**
   * 撤销整批(限时 30 分钟)。
   *
   * ⚠️ 语义是「**手滑 / 分错人**的补救」,不是"改主意重新调度" ——
   *   改主意应该走「客服退回」,那条路有完整的原因记录。
   * ⚠️ **几乎总是部分成功**:客服已经打开过的单不会被收回(他可能已经联系了患者),
   *   所以返回 revoked / skippedTouched / alreadyReleased 三个数 —— 界面必须如实显示,
   *   ⛔ 不能只弹一句「已撤销」。
   */
  revoke: (assignmentId: string) =>
    api.post<RevokeAssignmentResponse>(
      `/pac/v1/plans/assignments/${encodeURIComponent(assignmentId)}/revoke`,
      {},
    ),

  /**
   * 改本批福利 —— **确认之后仍然可以改**,空串 = 撤掉。
   *
   * ⚠️ 确认**之前**改福利不走这里:那时批次还没落库,福利跟着 `create` 一起写。
   *   这条路专治"点完确认才想起来要带福利" —— 此前那种情况卡片只改了自己的 state,
   *   亮了角标却什么也没写,主管看不出来(2026-08-06 实测)。
   */
  setBenefit: (assignmentId: string, text: string) =>
    api.post<SetAssignmentBenefitResponse>(
      `/pac/v1/plans/assignments/${encodeURIComponent(assignmentId)}/benefit`,
      { text },
    ),

  /**
   * 「重新排一版(尽量排满)」—— 卡片上那个按钮。
   *
   * ⚠️ 不经过助手:主管点的是按钮不是说话,走 HTTP 直接换掉那张卡。
   * ⚠️ 条件必须**原样带回**(人群 + 基数),否则重排会退回"沿用上一次",人数悄悄变了。
   */
  refill: (body: RefillProposalRequest) =>
    api.post<AssignmentProposal>('/pac/v1/plans/assignments/propose/refill', body),

  /**
   * 这一格圈定的**全部**患者(分页)—— 点格子之后、交给助手之前那张中间表。
   *
   * ⚠️ 与出确认单**同源**(服务端同一段 SQL + 同一个排序键):
   *   第 1 页看到的人就是助手会先挑走的那批。⛔ 前端别自己再排一次序。
   */
  cohort: (q: {
    clinicId: string;
    potentialTreatment?: string;
    temperature?: string;
    anchor?: AnchorModeValue;
    personaTags?: string;
    page?: number;
    pageSize?: number;
  }) =>
    api.get<CohortPage>('/pac/v1/plans/assignments/cohort', {
      query: {
        clinicId: q.clinicId,
        potentialTreatment: q.potentialTreatment,
        temperature: q.temperature,
        anchor: q.anchor,
        personaTags: q.personaTags,
        page: q.page == null ? undefined : String(q.page),
        pageSize: q.pageSize == null ? undefined : String(q.pageSize),
      },
    }),

  agents: (clinicId: string, include?: string[]) =>
    api.get<ListAgentsResponse>(
      `/pac/v1/plans/assignments/agents?clinicId=${encodeURIComponent(clinicId)}` +
        (include?.length ? `&include=${include.map(encodeURIComponent).join(',')}` : ''),
    ),
};
