import { useState, useRef, useEffect } from "react";
import { useNavigate } from "react-router";
import { X, Send, Minus, Lock, ArrowRight, Sparkles, Bot } from "lucide-react";
import { Button } from "./ui/button";
import { cn } from "./ui/utils";
import { useRole } from "../role-context";
import type { RoleId } from "../roles";

interface MsgAction {
  label: string;
  to: string;
}
interface Msg {
  role: "bot" | "user";
  text: string;
  actions?: MsgAction[];
}

type ProactiveType = "urgent" | "ai" | "todo" | "risk" | "suggestion";

interface Proactive {
  type: ProactiveType;
  title: string;
  content: string;
  to?: string;
  actionLabel?: string;
}

const TYPE_STYLE: Record<ProactiveType, { bg: string; border: string; title: string; badge: string }> = {
  urgent: { bg: "bg-[#fff3e0]", border: "border-[#ffcc80]", title: "text-[#e65100]", badge: "🔥" },
  ai: { bg: "bg-[#e3f2fd]", border: "border-[#90caf9]", title: "text-[#0d47a1]", badge: "✅" },
  todo: { bg: "bg-[#e8f0fe]", border: "border-[#a3c2f0]", title: "text-[#1565c0]", badge: "📋" },
  risk: { bg: "bg-[#ffebee]", border: "border-[#ef9a9a]", title: "text-[#c62828]", badge: "⚠️" },
  suggestion: { bg: "bg-[#f5f5f5]", border: "border-[#e0e0e0]", title: "text-[#455a64]", badge: "💡" },
};

// 各角色的主动提醒(最多 3~4 条，按优先级)
const PROACTIVE: Partial<Record<RoleId, Proactive[]>> = {
  specialist: [
    { type: "urgent", title: "BID-2026-005 今日需开标", content: "「2026年度防腐保温工程框架」已到开标时间，请立即组织评标。", to: "/app/projects", actionLabel: "去处理" },
    { type: "ai", title: "AI 智慧寻源已完成", content: "「年产5万吨聚丙烯项目」已自动寻源，匹配到 12 家潜在供应商，请确认寻源结果。", to: "/app/projects/P2026005/sourcing", actionLabel: "查看结果" },
    { type: "todo", title: "您有 3 个委托单待受理", content: "来自采购需求人员的委托申请已提交，请及时受理并立项。", to: "/app/projects", actionLabel: "去受理" },
  ],
  requester: [
    { type: "ai", title: "阀门采购项目已定标", content: "您的「氯碱车间耐腐蚀阀门采购」已完成定标，下一步请进入 SRM 生成采购合同。", to: "/app/projects", actionLabel: "查看项目" },
    { type: "todo", title: "2 个 AI 预填委托单待确认", content: "AI 已根据采购计划为您预填委托单，确认无误后即可提交立项。", to: "/app/delegation", actionLabel: "去确认" },
  ],
  expert: [
    { type: "urgent", title: "保温材料招标项目评标邀请", content: "您有一个「保温材料招标项目」的评标邀请，可以选择接受或拒绝，点击查看详情。", to: "/app/expert-tasks", actionLabel: "查看详情" },
    { type: "todo", title: "《评标纪律承诺书》待签署", content: "进入评审前需先签署当前项目的评标纪律承诺书。", to: "/app/expert-tasks", actionLabel: "去签署" },
  ],
  supplier: [
    { type: "ai", title: "聚丙烯项目报名已通过", content: "您在「年产5万吨聚丙烯项目」中的报名已通过，请查看招标文件；如确认投标，可缴纳投标保证金。", to: "/app/bidding", actionLabel: "查看招标文件" },
    { type: "urgent", title: "报名即将截止", content: "「污水处理提标改造工程」报名将于 7月15日截止，请尽快完成报名。", to: "/app/bidding", actionLabel: "去报名" },
  ],
  committee: [
    { type: "risk", title: "异常决策待处理", content: "检测到 1 个项目触发异常上报（有效投标人不足 3 家），需领导小组决策。", to: "/app/exceptions", actionLabel: "去处理" },
  ],
  auditor: [
    { type: "risk", title: "围串标风险提示", content: "AI 检测到 1 组投标文件相似度偏高，建议核查。", to: "/app/collusion", actionLabel: "去核查" },
  ],
};

const quickReplies = [
  "如何发起招标委托?",
  "帮我统计本年度项目预算总和",
  "在线评标怎么打分?",
  "公开招标和邀请招标的区别?",
];

interface Knowledge {
  text: string;
  actions?: MsgAction[];
}

const knowledge: { key: string; ans: Knowledge }[] = [
  {
    key: "委托",
    ans: {
      text:
        "发起招标委托很简单：①点击工作台或项目管理页的「发起委托」按钮；②在「填写需求」步骤用自然语言描述需求，点击「AI 智能解析」即可自动生成《招标委托书》；③确认预填单后提交审批即可。",
      actions: [{ label: "现在去发起委托", to: "/app/delegation" }],
    },
  },
  {
    key: "统计",
    ans: {
      text: "据统计，本年度一共有 13 个项目，预算总和为 12,348 万元。",
      actions: [{ label: "查看项目列表", to: "/app/projects" }],
    },
  },
  {
    key: "预算",
    ans: {
      text: "据统计，本年度一共有 13 个项目，预算总和为 12,348 万元。",
      actions: [{ label: "查看项目列表", to: "/app/projects" }],
    },
  },
  {
    key: "区别",
    ans: {
      text:
        "公开招标面向所有符合条件的供应商发布寻源公告，参与方需报名审核；邀请招标则由您从长名单中筛选短名单进行定向邀请。招标方式在需求委托阶段即已确定，两者均支持全流程线上闭环。",
    },
  },
  {
    key: "评标",
    ans: {
      text:
        "进入「在线评标室」后：左栏选择匿名投标人，中栏查看脱敏标书，右栏按技术分/商务分/价格分录入分数并填写评分说明，系统会同步展示 AI 雷同检测与价格合理性分析，最后点击「提交评分」。",
      actions: [{ label: "进入在线评标室", to: "/app/projects/P2026001/evaluation" }],
    },
  },
  {
    key: "入库",
    ans: {
      text:
        "供应商在「供应商管理」中提交入库申请，AI 会自动核验工商与风险信息；审核通过后系统将自动入库，无需单独操作。",
      actions: [{ label: "前往供应商管理", to: "/app/suppliers" }],
    },
  },
  {
    key: "上传",
    ans: {
      text:
        "进入「投标中心」→ 选择项目 → 在「上传投标文件」区域上传文件，系统会自动加密并上链存证。开标前任何人都无法查看，投标截止前还可撤回重传。",
      actions: [{ label: "进入投标中心", to: "/app/bidding" }],
    },
  },
];

const dataKeywords = ["报价", "投标价", "多少钱", "金额", "中标", "得分", "分数", "名单", "谁"];

type PageType = "app" | "portal" | "login";

function getPointer(e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) {
  if ("touches" in e && e.touches.length > 0) {
    return { x: e.touches[0].clientX, y: e.touches[0].clientY };
  }
  if ("changedTouches" in e && e.changedTouches.length > 0) {
    return { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY };
  }
  if ("clientX" in e) {
    return { x: e.clientX, y: e.clientY };
  }
  return { x: 0, y: 0 };
}

const ENTRY_PROACTIVE: Proactive[] = [
  {
    type: "todo",
    title: "欢迎使用智慧招标平台",
    content: "您可以直接从首页查看交易信息、政策法规与操作指南。",
    to: "/portal/trading-info",
    actionLabel: "查看交易信息",
  },
  {
    type: "ai",
    title: "新用户建议先注册",
    content: "供应商用户可先完成注册与实名认证，后续即可参与报名与投标。",
    to: "/register",
    actionLabel: "立即注册",
  },
];

export function XiaobinAssistant({ pageType = "app" }: { pageType?: PageType }) {
  const { sensitive, role, roleId } = useRole();
  const navigate = useNavigate();
  // 工作台默认展开；首页/登录页默认收起，避免遮挡主内容
  const [open, setOpen] = useState(pageType === "app");
  const [showChat, setShowChat] = useState(false);
  const [input, setInput] = useState("");
  const [proactive, setProactive] = useState<Proactive[]>(
    pageType === "app" ? PROACTIVE[roleId] ?? [] : ENTRY_PROACTIVE,
  );
  const [msgs, setMsgs] = useState<Msg[]>([
    {
      role: "bot",
      text: "您好，我是智能助手「小滨」👋 我可以为您解答系统操作与业务咨询。注意：我不参与任何业务决策哦。请问有什么可以帮您？",
    },
  ]);
  const endRef = useRef<HTMLDivElement>(null);
  const dragRef = useRef({ dragging: false, dx: 0, dy: 0, sx: 0, sy: 0, moved: false });
  const [pos, setPos] = useState({ x: 0, y: 0 });
  const [dragging, setDragging] = useState(false);
  const EDGE_GAP = 20;

  const panelSize = open ? { w: 360, h: 520 } : { w: 68, h: 68 };

  function clamp(x: number, y: number) {
    const pad = EDGE_GAP;
    const maxX = Math.max(pad, window.innerWidth - panelSize.w - pad);
    const maxY = Math.max(pad, window.innerHeight - panelSize.h - pad);
    return {
      x: Math.min(Math.max(x, pad), maxX),
      y: Math.min(Math.max(y, pad), maxY),
    };
  }

  function startDrag(e: React.MouseEvent | React.TouchEvent) {
    const p = getPointer(e);
    dragRef.current.dragging = true;
    dragRef.current.sx = p.x;
    dragRef.current.sy = p.y;
    dragRef.current.moved = false;
    setDragging(true);
    dragRef.current.dx = p.x - pos.x;
    dragRef.current.dy = p.y - pos.y;
  }

  function snapToEdge(x: number, y: number) {
    const pad = EDGE_GAP;
    const maxX = Math.max(pad, window.innerWidth - panelSize.w - pad);
    const maxY = Math.max(pad, window.innerHeight - panelSize.h - pad);
    const targetX = x <= maxX / 2 ? pad : maxX;
    return {
      x: targetX,
      y: Math.min(Math.max(y, pad), maxY),
    };
  }

  // 切换角色时刷新主动提醒
  useEffect(() => {
    if (pageType === "app") setProactive(PROACTIVE[roleId] ?? []);
  }, [roleId, pageType]);

  useEffect(() => {
    if (showChat) endRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [msgs, showChat]);

  // 初始位置（右下角）
  useEffect(() => {
    const w = pageType === "app" ? 360 : 68;
    const h = pageType === "app" ? 520 : 68;
    const p = clamp(window.innerWidth - w - 32, window.innerHeight - h - 32);
    setPos(p);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pageType]);

  useEffect(() => {
    function onMove(e: MouseEvent | TouchEvent) {
      if (!dragRef.current.dragging) return;
      const p = getPointer(e);
      if (!dragRef.current.moved && (Math.abs(p.x - dragRef.current.sx) > 4 || Math.abs(p.y - dragRef.current.sy) > 4)) {
        dragRef.current.moved = true;
      }
      const next = clamp(p.x - dragRef.current.dx, p.y - dragRef.current.dy);
      setPos(next);
    }
    function onUp() {
      if (!dragRef.current.dragging) return;
      dragRef.current.dragging = false;
      setDragging(false);
      setPos((prev) => snapToEdge(prev.x, prev.y));
    }
    function onResize() {
      setPos((prev) => clamp(prev.x, prev.y));
    }
    window.addEventListener("mousemove", onMove);
    window.addEventListener("touchmove", onMove, { passive: false });
    window.addEventListener("mouseup", onUp);
    window.addEventListener("touchend", onUp);
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("touchmove", onMove);
      window.removeEventListener("mouseup", onUp);
      window.removeEventListener("touchend", onUp);
      window.removeEventListener("resize", onResize);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const gradient = `linear-gradient(135deg, ${role.bannerFrom}, ${role.bannerTo})`;
  const unread = proactive.length;

  function answer(q: string): Knowledge {
    if (sensitive && dataKeywords.some((k) => q.includes(k))) {
      return {
        text: "当前为流程敏感期（如开标前），数据类问题暂无法回答。请等待系统通知。我可以继续为您讲解系统操作哦~",
      };
    }
    const hit = knowledge.find((k) => q.includes(k.key));
    return (
      hit?.ans ?? {
        text:
          "这是一个很好的问题。作为操作助手，我建议您查阅对应模块的帮助说明，或描述更具体的操作场景，我会尽力为您讲解系统使用方法。（温馨提示：业务决策需由有权限的人员完成）",
      }
    );
  }

  function send(text: string) {
    const q = text.trim();
    if (!q) return;
    setShowChat(true);
    setMsgs((m) => [...m, { role: "user", text: q }]);
    setInput("");
    setTimeout(() => {
      const a = answer(q);
      setMsgs((m) => [...m, { role: "bot", text: a.text, actions: a.actions }]);
    }, 500);
  }

  function handleAction(p: Proactive) {
    if (p.to) navigate(p.to);
  }

  return (
    <div
      className={cn(
        "fixed z-50",
        open ? "border bg-card shadow-2xl" : "border-0 bg-transparent shadow-none",
        open ? "overflow-hidden" : "overflow-visible",
        dragging ? "" : "transition-[left,top,width,height,border-radius] duration-260 ease-out",
      )}
      style={{
        left: pos.x,
        top: pos.y,
        width: open ? 360 : 68,
        height: open ? 520 : 68,
        borderRadius: open ? 16 : "9999px",
      }}
      onClick={() => {
        if (!open && !dragRef.current.moved) setOpen(true);
      }}
    >
      {!open && (
        <div
          onMouseDown={startDrag}
          onTouchStart={startDrag}
          className="relative flex size-full cursor-grab items-center justify-center rounded-full text-white shadow-xl ring-1 ring-white/35 active:cursor-grabbing"
          style={{ backgroundImage: gradient }}
          aria-label="打开小滨 AI 助手"
        >
          <span className="pointer-events-none absolute inset-0 rounded-full animate-breathe" style={{ backgroundImage: gradient }} />
          <span className="relative flex flex-col items-center leading-none">
            <span className="flex size-8 items-center justify-center rounded-full bg-white/22 ring-1 ring-white/35">
              <Bot className="size-4.5" />
            </span>
            <span className="mt-1 text-[10px] font-medium text-white/95">小滨</span>
          </span>
          {unread > 0 && (
            <span className="absolute right-0 top-0 z-10 flex size-5 translate-x-1/3 -translate-y-1/3 items-center justify-center rounded-full border-2 border-white bg-[#f44336] text-[10px] font-bold text-white shadow-sm">
              {unread}
            </span>
          )}
        </div>
      )}

      <div
        className={cn(
          "flex h-full w-full flex-col",
          open ? "opacity-100" : "pointer-events-none opacity-0",
          dragging ? "" : "transition-opacity duration-180",
        )}
      >
        {/* 头部 */}
        <div
          className="flex cursor-move items-center justify-between px-4 py-3 text-white"
          style={{ backgroundImage: gradient }}
          onMouseDown={startDrag}
          onTouchStart={startDrag}
        >
          <div className="flex items-center gap-2.5">
            <div className="flex size-9 items-center justify-center rounded-full bg-white/20 text-sm font-bold">滨</div>
            <div className="leading-tight">
              <div className="text-sm font-semibold">小滨 AI 助手</div>
              <div className="flex items-center gap-1 text-[11px] text-white/85">
                <span className="size-1.5 rounded-full bg-emerald-300" /> 在线 · 已为您分析今日待办
              </div>
            </div>
          </div>
          <button onClick={() => setOpen(false)} className="rounded-md p-1 hover:bg-white/15" title="收起">
            <Minus className="size-4" />
          </button>
        </div>

        {sensitive && (
          <div className="flex items-center gap-1.5 border-b bg-amber-50 px-4 py-2 text-xs text-amber-700">
            <Lock className="size-3.5" /> 当前为流程敏感期，数据类问题暂无法回答
          </div>
        )}

        <div className="flex-1 space-y-3 overflow-y-auto bg-muted/30 p-4">
          {!showChat ? (
            <>
              <div className="flex items-center justify-between">
                <span className="text-xs font-medium text-muted-foreground">
                  📢 为您整理的今日提醒（{proactive.length}）
                </span>
                {proactive.length > 0 && (
                  <button
                    onClick={() => setShowChat(true)}
                    className="text-xs text-primary hover:underline"
                  >
                    去提问 →
                  </button>
                )}
              </div>
              {proactive.length === 0 && (
                <div className="rounded-xl border bg-card p-4 text-center text-sm text-muted-foreground">
                  🎉 暂无待办，继续保持！
                </div>
              )}
              {proactive.map((p, i) => {
                const st = TYPE_STYLE[p.type];
                return (
                  <div key={i} className={cn("animate-slide-up rounded-xl border p-3", st.bg, st.border)}>
                    <div className="flex items-start justify-between gap-2">
                      <div className={cn("text-[13px] font-bold", st.title)}>
                        {st.badge} {p.title}
                      </div>
                      <button
                        onClick={() => setProactive((ps) => ps.filter((_, idx) => idx !== i))}
                        className="text-muted-foreground/60 hover:text-muted-foreground"
                      >
                        <X className="size-3.5" />
                      </button>
                    </div>
                    <p className="mt-1 text-xs leading-relaxed text-[#4a5568]">{p.content}</p>
                    {p.to && (
                      <button
                        onClick={() => handleAction(p)}
                        className={cn("mt-2 inline-flex items-center gap-0.5 rounded-md bg-white/70 px-2 py-1 text-xs font-bold", st.title)}
                      >
                        {p.actionLabel ?? "去处理"} <ArrowRight className="size-3" />
                      </button>
                    )}
                  </div>
                );
              })}
              <div className="pt-1">
                <p className="mb-2 text-xs text-muted-foreground">猜你想问：</p>
                <div className="space-y-2">
                  {quickReplies.map((q) => (
                    <button
                      key={q}
                      onClick={() => send(q)}
                      className="block w-full rounded-lg border bg-card px-3 py-2 text-left text-xs text-foreground transition-colors hover:border-primary hover:text-primary"
                    >
                      {q}
                    </button>
                  ))}
                </div>
              </div>
            </>
          ) : (
            <>
              <button onClick={() => setShowChat(false)} className="text-xs text-primary hover:underline">
                ← 返回待办提醒
              </button>
              {msgs.map((m, i) => (
                <div key={i} className={cn("flex", m.role === "user" ? "justify-end" : "justify-start")}>
                  <div
                    className={cn(
                      "max-w-[85%] rounded-2xl px-3.5 py-2.5 text-sm leading-relaxed",
                      m.role === "user"
                        ? "rounded-br-sm bg-primary text-primary-foreground"
                        : "rounded-bl-sm border bg-card text-card-foreground",
                    )}
                  >
                    <div>{m.text}</div>
                    {m.actions && m.actions.length > 0 && (
                      <div className="mt-2 flex flex-wrap gap-2">
                        {m.actions.map((a) => (
                          <button
                            key={a.to}
                            onClick={() => navigate(a.to)}
                            className="inline-flex items-center gap-1 rounded-lg bg-primary px-2.5 py-1.5 text-xs font-medium text-primary-foreground hover:opacity-90"
                          >
                            <Sparkles className="size-3.5" /> {a.label}
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              ))}
              <div ref={endRef} />
            </>
          )}
        </div>

        <div className="flex items-center gap-2 border-t bg-card p-3">
          <input
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && send(input)}
            placeholder="输入您的问题…"
            className="h-9 flex-1 rounded-full border bg-input-background px-3.5 text-sm outline-none focus:border-primary"
          />
          <Button size="icon" onClick={() => send(input)} className="size-9 shrink-0 rounded-full" style={{ backgroundImage: gradient }}>
            <Send className="size-4" />
          </Button>
        </div>
      </div>
    </div>
  );
}
