'use client';

import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Inbox, RefreshCw } from 'lucide-react';
import { Permission } from '@pac/types';
import { Can } from '@/components/can';
import { useHasPermission } from '@/hooks/use-permission';
import { plansApi } from '@/components/plans/plans-api';
import { PatientPickerRail } from '@/components/plans/patient-picker-rail';
import { IdentityCluster } from '@/components/identity-cluster';
import { isEmbedded } from '@/lib/embed';

/**
 * /plans — 工作台入口解析器(原独立列表页已废除,左栏 patient-picker-rail 取代了它)。
 *
 * 进来直接落到详情工作台,选人规则(纯规则):
 *   ① 我的「进行中」第一个(优先续上手头工作)
 *   ② 没有 → 召回池优先级最高的一个(开新工作)
 *   ③ 都没有 → 空工作台:左栏照常(可自行调筛选找人)+ 右侧整体空态
 * 所有旧入口(/ 重定向、各处"返回召回池"链接)自动适配 —— 都会被本页弹回详情。
 */
export default function PlansEntryPage() {
  return (
    <Can perm={Permission.PLAN_VIEW_OWN}>
      <EntryResolver />
    </Can>
  );
}

function EntryResolver() {
  const router = useRouter();
  /// 主管判据(T16):只有他有召回池,客服的落地兜底不能滑进池子
  const canDispatch = useHasPermission(Permission.PLAN_DISPATCH);
  const [phase, setPhase] = useState<'resolving' | 'empty'>('resolving');

  useEffect(() => {
    let cancelled = false;
    /**
     * 🔴 **主管落到主管工作台，⛔ 不再滑进某个患者的详情页**（2026-08-07 产品定）。
     *
     * 在此之前主管和客服走**同一条**落地规则：先我的进行中、再召回池第一个 ——
     * 于是他一登录就站在**某一个患者**的详情页上，而他这一屏要做的是
     * "我这周分了多少、拿回来多少、下一批分给谁"。这与 08-04 评审那句
     * 「场景和思路不应该去混」是同一个问题的两面（见 doctrine 里被改写的 T16）。
     *
     * ⚠️ 这只改**落地默认**，⛔ 不是把执行页锁掉：
     *   主管本质也是客服，他从工作台头部的「客服执行页 ↗」照样进得来，
     *   进来之后下面那套规则原样生效（所以它一行都没删）。
     * ⭐ 这里**不存在**"权限还没加载完就抢跑"的问题：`permissions` 来自 **JWT 即时解码**，
     *   而 `AuthGate` 拿到 token 才渲染 children —— 本组件挂载时它一定已经在了。
     *   ⚠️ 别把它和 `clinicIds` 搞混：**那个**才是 `/auth/session` 异步回来的
     *   （工作台的诊所选择器就为此踩过 —— 第一帧锁错诊所，两栏数据对不上却不报错）。
     */
    /**
     * ⚠️ `?exec=1` = **主管明确要来执行页**（工作台头部那个「客服执行页 ↗」带的）。
     *
     * 🔴 不给这个出口，那个链接就是**死的**（2026-08-07 实测）：点它 → `/plans` →
     *   这里又把他弹回 `/supervisor`，肉眼看就是"没反应"。
     *   落地默认要改，但**明确的导航意图不能被默认覆盖**。
     * ⚠️ 读 `window.location.search` 而不是 `useSearchParams()`：后者会让这张静态页
     *   退化成必须包 Suspense 的 CSR bailout，为一个开关不值当。
     */
    const wantsExec =
      typeof window !== 'undefined' && new URLSearchParams(window.location.search).has('exec');
    if (canDispatch && !wantsExec) {
      router.replace('/supervisor');
      return;
    }
    (async () => {
      try {
        // ① 我的进行中(优先级最高的一个)
        const mine = await plansApi.list({ view: 'mine', status: 'assigned', sort: 'priority_desc', page: 1, pageSize: 1 });
        if (cancelled) return;
        if (mine.items[0]) {
          router.replace(`/plans/${mine.items[0].id}`);
          return;
        }
        // ② 召回池第一个 —— ⭐ **仅主管**。
        //   客服没有召回池入口(T16),这里若不门控就是一条隐式的认领通道:
        //   他的「我的」一空,系统就自动把他送进池子里某个患者的详情页,
        //   而那个人根本不是分给他的。tab 藏了没用,路径也得堵。
        if (canDispatch) {
          const pool = await plansApi.list({ view: 'pool', sort: 'priority_desc', page: 1, pageSize: 1 });
          if (cancelled) return;
          if (pool.items[0]) {
            router.replace(`/plans/${pool.items[0].id}`);
            return;
          }
        }
        setPhase('empty');
      } catch {
        if (!cancelled) setPhase('empty');
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [router, canDispatch]);

  if (phase === 'resolving') {
    return (
      <div className="flex h-screen items-center justify-center gap-2 text-sm text-muted-foreground">
        <span className="h-4 w-4 animate-spin rounded-full border-2 border-brand-500 border-t-transparent" />
        正在进入召回工作台…
      </div>
    );
  }

  // ③ 空工作台:左栏可用(调筛选自己找人),右侧整体空态
  return (
    <div className="flex h-screen flex-col overflow-hidden bg-slate-50">
      {/* 空态 header —— 内容只有 PAC 品牌 + 用户三件套,无功能项;嵌入宿主时整体隐藏 */}
      {!isEmbedded() && (
        <header className="flex h-12 flex-none items-center gap-2 border-b border-slate-100 bg-white px-4">
          <span className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-brand-600 text-[12px] font-bold text-white">
            PAC
          </span>
          <h1 className="text-[14px] font-semibold text-slate-900">召回工作台</h1>
          <div className="ml-auto flex items-center gap-2">
            <IdentityCluster />
          </div>
        </header>
      )}
      <div className="flex min-h-0 flex-1">
        <PatientPickerRail currentPlanId="" />
        <div className="flex min-w-0 flex-1 flex-col items-center justify-center gap-3 text-center">
          <span className="inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-slate-100 text-slate-400">
            <Inbox className="h-7 w-7" />
          </span>
          <div className="text-[15px] font-medium text-slate-700">
            {canDispatch ? '当前没有待跟进的召回任务' : '暂无分配给你的任务'}
          </div>
          {/* ⭐ 客服看到的空态不能提"召回池"——他没有那个入口,提了只会让他去找一个不存在的地方。
              主管的空态照旧(他确实两边都能看)。 */}
          <p className="max-w-sm text-[12.5px] leading-relaxed text-slate-500">
            {canDispatch
              ? '我的任务与召回池都是空的。可以在左侧调整筛选(视图 / 诊所 / 筛选标签)自行查找,或等召回引擎下次重算后刷新。'
              : '手头的任务都处理完了。新任务由主管统一派发,稍后刷新看看。'}
          </p>
          <button
            type="button"
            onClick={() => window.location.reload()}
            className="inline-flex items-center gap-1.5 rounded-md border border-slate-100 bg-white px-3 py-1.5 text-[12.5px] text-slate-600 hover:bg-slate-50"
          >
            <RefreshCw className="h-3.5 w-3.5" />
            刷新
          </button>
        </div>
      </div>
    </div>
  );
}
