import { useEffect, useState } from "react";
import { App as AntApp } from "antd";
import {
  PlusOutlined,
  EditOutlined,
  DeleteOutlined,
  SaveOutlined,
  CloseOutlined,
  AppstoreOutlined,
  FileExcelOutlined,
  KeyOutlined,
  RollbackOutlined,
  SettingOutlined,
} from "@ant-design/icons";
import {
  Field,
  PrimInput,
  PrimSelect,
  PrimCheckbox,
  ToolbarBtnDark,
} from "@/components/Primitives";
import StaffPicker from "@/components/StaffPicker";
import {
  createUser,
  getUser,
  listPermissionCategories,
  updateUser,
  type PermissionCategoryVO,
  type UserDTO,
  type UserListVO,
} from "@/api/user";
import {
  USER_TYPES,
  LANGUAGE_OPTIONS,
  SCOPE_ITEMS,
} from "@/utils/data";
import { useAppDispatch, useAppSelector } from "@/store";
import { closeTab, setActiveTab } from "@/store/tabsSlice";
import { fmtDateTime } from "@/utils/format";

type Mode = "view" | "edit" | "new";

interface Props {
  userId?: number;
  mode: Mode;
}

interface FormState {
  sUserNo: string;
  sUserName: string;
  iStaffId: number | null;
  staffName: string;
  sUserType: string;
  sLanguage: string;
  bCanModifyDocs: boolean;
}

const PERM_TABS = [
  { id: "groups", label: "权限组" },
  { id: "customer", label: "客户查看权限" },
  { id: "supplier", label: "供应商查看权限" },
  { id: "staff", label: "人员查看权限" },
  { id: "process", label: "工序查看权限" },
  { id: "driver", label: "司机查看权限" },
];

export default function UserDetail({ userId, mode: initialMode }: Props) {
  const [mode, setMode] = useState<Mode>(initialMode);
  const [submitting, setSubmitting] = useState(false);
  const dispatch = useAppDispatch();
  const { message } = AntApp.useApp();
  const tabs = useAppSelector((s) => s.tabs.tabs);
  const activeTabId = useAppSelector((s) => s.tabs.activeTabId);
  const tab = tabs.find((t) => t.id === activeTabId);
  const snapshot = tab?.meta?.snapshot as UserListVO | undefined;
  const [detail, setDetail] = useState<UserListVO | undefined>(snapshot);
  const currentSnapshot = detail ?? snapshot;
  const [permissionCategories, setPermissionCategories] = useState<PermissionCategoryVO[]>([]);
  // null = 详情尚未加载（仅在新建模式下立即视为 []）。
  // 编辑模式必须等到非 null 后才允许保存，否则会把"未知"误当成"清空"。
  const [permissionCategoryIds, setPermissionCategoryIds] = useState<number[] | null>(
    initialMode === "new" ? [] : null
  );

  const buildForm = (snap?: UserListVO): FormState =>
    mode === "new" || !snap
      ? {
          sUserNo: "",
          sUserName: "",
          iStaffId: null,
          staffName: "",
          sUserType: "普通用户",
          sLanguage: "zh",
          bCanModifyDocs: false,
        }
      : {
          sUserNo: snap.sUserNo,
          sUserName: snap.sUserName,
          iStaffId: snap.iStaffId,
          staffName: snap.staffName ?? "",
          sUserType: snap.sUserType,
          sLanguage: snap.sLanguage,
          bCanModifyDocs: !!snap.bCanModifyDocs,
        };

  const [form, setForm] = useState<FormState>(() => buildForm(currentSnapshot));
  const [permTab, setPermTab] = useState("groups");
  const [tabPerms, setTabPerms] = useState<Record<string, boolean>>({});

  useEffect(() => {
    setDetail(snapshot);
  }, [snapshot]);

  useEffect(() => {
    void listPermissionCategories()
      .then(setPermissionCategories)
      .catch(() => {
        // interceptor already showed message
      });
  }, []);

  useEffect(() => {
    if (mode === "new" || !userId) return;
    void getUser(userId)
      .then((u) => {
        setDetail(u);
        setPermissionCategoryIds(u.permissionCategoryIds ?? []);
      })
      .catch(() => {
        // interceptor already showed message; 保持 null 以便"修改/保存"维持 disabled。
      });
  }, [mode, userId]);

  useEffect(() => {
    setForm(buildForm(currentSnapshot));
    if (mode === "new") {
      setPermissionCategoryIds([]);
    } else if (currentSnapshot?.permissionCategoryIds !== undefined) {
      // detail() 返回过来的快照里带 ids 才采纳；列表态快照没有该字段时保持 null（仍未加载）。
      setPermissionCategoryIds(currentSnapshot.permissionCategoryIds);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentSnapshot, mode]);

  const set = <K extends keyof FormState>(k: K, v: FormState[K]) =>
    setForm((s) => ({ ...s, [k]: v }));

  const disabled = mode === "view";
  const checkedCount = permissionCategoryIds?.length ?? 0;
  const permsLoaded = permissionCategoryIds !== null;

  const startEdit = () => setMode("edit");
  const startNew = () => setMode("new");
  const cancel = () => {
    if (mode === "new") {
      dispatch(closeTab(activeTabId));
      dispatch(setActiveTab("userlist"));
    } else {
      setForm(buildForm(currentSnapshot));
      if (currentSnapshot?.permissionCategoryIds !== undefined) {
        setPermissionCategoryIds(currentSnapshot.permissionCategoryIds);
      }
      setMode("view");
    }
  };

  const save = async () => {
    if (!form.sUserNo.trim() || !form.sUserName.trim() || !form.sUserType || !form.sLanguage) {
      message.error("请填写必填项");
      return;
    }
    const dto: UserDTO = {
      sUserNo: form.sUserNo,
      sUserName: form.sUserName,
      iStaffId: form.iStaffId,
      sUserType: form.sUserType,
      sLanguage: form.sLanguage,
      bCanModifyDocs: form.bCanModifyDocs,
    };
    if (mode === "new") {
      dto.permissionCategoryIds = permissionCategoryIds ?? [];
    } else if (permissionCategoryIds !== null) {
      // 编辑模式：未加载完前不下发该字段，后端按"不动权限"处理。
      dto.permissionCategoryIds = permissionCategoryIds;
    }
    setSubmitting(true);
    try {
      if (mode === "new") {
        await createUser(dto);
        message.success("新增成功");
        dispatch(closeTab(activeTabId));
        dispatch(setActiveTab("userlist"));
      } else if (userId) {
        await updateUser(userId, dto);
        const refreshed = await getUser(userId);
        setDetail(refreshed);
        setPermissionCategoryIds(refreshed.permissionCategoryIds ?? []);
        message.success("保存成功");
        setMode("view");
      }
    } catch {
      // interceptor
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        height: "100%",
        background: "var(--bg-app)",
        position: "relative",
      }}
    >
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 2,
          flexWrap: "wrap",
          rowGap: 4,
          padding: "4px 8px",
          background: "var(--bg-toolbar-dark)",
          flex: "none",
          borderBottom: "1px solid #1a1f2a",
        }}
      >
        <ToolbarBtnDark icon={<PlusOutlined />} onClick={startNew} disabled={mode !== "view"}>
          新增
        </ToolbarBtnDark>
        <ToolbarBtnDark
          icon={<EditOutlined />}
          onClick={startEdit}
          disabled={mode !== "view" || !userId || !permsLoaded}
        >
          修改
        </ToolbarBtnDark>
        <ToolbarBtnDark icon={<DeleteOutlined />} disabled={mode !== "view"} danger>
          删除
        </ToolbarBtnDark>
        <ToolbarBtnDark
          icon={<SaveOutlined />}
          onClick={save}
          disabled={mode === "view" || submitting || (mode === "edit" && !permsLoaded)}
        >
          保存
        </ToolbarBtnDark>
        <ToolbarBtnDark icon={<CloseOutlined />} onClick={cancel} disabled={mode === "view"}>
          取消
        </ToolbarBtnDark>
        <span
          style={{
            width: 1,
            height: 16,
            background: "rgba(255,255,255,0.12)",
            margin: "0 4px",
          }}
        />
        <ToolbarBtnDark icon={<AppstoreOutlined />}>功能</ToolbarBtnDark>
        <ToolbarBtnDark icon={<FileExcelOutlined />}>作废</ToolbarBtnDark>
        <ToolbarBtnDark icon={<KeyOutlined />}>重置密码</ToolbarBtnDark>
        <ToolbarBtnDark icon={<RollbackOutlined />}>取消作废</ToolbarBtnDark>
        <div style={{ flex: 1 }} />
        <span style={{ fontSize: 11, color: "var(--text-on-dark-muted)", marginRight: 8 }}>
          已选权限：
          <span style={{ color: "#fff", fontWeight: 500 }}>{checkedCount}</span> /{" "}
          {permissionCategories.length}
        </span>
        <span
          style={{
            padding: "2px 8px",
            fontSize: 11,
            background:
              mode === "view"
                ? "rgba(39,165,103,0.18)"
                : mode === "new"
                  ? "rgba(58,142,224,0.22)"
                  : "rgba(217,142,31,0.22)",
            color:
              mode === "view"
                ? "#7be0a8"
                : mode === "new"
                  ? "#9cc8f0"
                  : "#ffc77a",
            border: `1px solid ${
              mode === "view"
                ? "rgba(39,165,103,0.4)"
                : mode === "new"
                  ? "rgba(58,142,224,0.4)"
                  : "rgba(217,142,31,0.4)"
            }`,
          }}
        >
          {mode === "view" ? "只读" : mode === "new" ? "新增中" : "编辑中"}
        </span>
        <button
          style={{
            marginLeft: 8,
            width: 22,
            height: 22,
            border: "none",
            background: "transparent",
            color: "var(--text-on-dark-muted)",
            cursor: "pointer",
          }}
        >
          <SettingOutlined />
        </button>
      </div>

      <div
        style={{
          background: "#fff",
          padding: "10px 12px",
          borderBottom: "1px solid var(--border)",
          flex: "none",
          display: "grid",
          gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))",
          rowGap: 6,
          columnGap: 16,
        }}
      >
        <Field label="创建时间">
          <PrimInput
            value={
              mode === "new"
                ? "保存后自动生成"
                : fmtDateTime(currentSnapshot?.tCreateDate)
            }
            disabled
            mono
          />
        </Field>
        <Field label="制单人" required>
          <PrimInput
            value={mode === "new" ? "保存后自动生成" : currentSnapshot?.sCreatedBy ?? ""}
            disabled
            required
          />
        </Field>
        <Field label="员工名" required>
          <StaffPicker
            value={form.staffName}
            onChange={(name, id) =>
              setForm((s) => ({
                ...s,
                staffName: name,
                iStaffId: id,
                // Auto-fill 用户号 / 用户名 to the staff name on selection
                // (matches prototype behavior — user can still override after).
                ...(id != null ? { sUserNo: name, sUserName: name } : {}),
              }))
            }
            disabled={disabled}
            required
            placeholder="输入员工姓名搜索"
          />
        </Field>

        <Field label="用户名" required>
          <PrimInput
            value={form.sUserName}
            onChange={(v) => set("sUserName", v)}
            disabled={disabled}
            required
          />
        </Field>
        <Field label="类型" required>
          <PrimSelect
            value={form.sUserType}
            onChange={(v) => set("sUserType", v)}
            disabled={disabled}
            required
            allowEmpty={false}
            options={USER_TYPES}
          />
        </Field>
        <Field label="用户号" required>
          <PrimInput
            value={form.sUserNo}
            onChange={(v) => set("sUserNo", v)}
            disabled={disabled}
            required
            mono
          />
        </Field>

        <Field label="语言" required>
          <PrimSelect
            value={form.sLanguage}
            onChange={(v) => set("sLanguage", v)}
            disabled={disabled}
            required
            allowEmpty={false}
            options={LANGUAGE_OPTIONS}
          />
        </Field>
        <Field label="单据修改权限">
          <div
            style={{
              flex: 1,
              height: "var(--input-h)",
              display: "flex",
              alignItems: "center",
              paddingLeft: 4,
              border: "1px solid var(--border-input)",
              background: disabled ? "var(--bg-disabled)" : "var(--bg-input)",
            }}
          >
            <PrimCheckbox
              checked={form.bCanModifyDocs}
              onChange={(v) => set("bCanModifyDocs", v)}
              disabled={disabled}
            />
          </div>
        </Field>
      </div>

      <div
        style={{
          display: "flex",
          alignItems: "stretch",
          background: "#fff",
          borderBottom: "1px solid var(--border)",
          flex: "none",
        }}
      >
        {PERM_TABS.map((t) => {
          const active = t.id === permTab;
          return (
            <div
              key={t.id}
              onClick={() => setPermTab(t.id)}
              style={{
                padding: "6px 14px",
                fontSize: 12,
                cursor: "pointer",
                color: active ? "var(--accent-strong)" : "var(--text)",
                background: active ? "var(--accent-soft)" : "transparent",
                borderTop: active ? "2px solid var(--accent)" : "2px solid transparent",
                borderRight: "1px solid var(--border)",
                fontWeight: active ? 500 : 400,
              }}
              onMouseEnter={(e) => {
                if (!active) e.currentTarget.style.background = "var(--bg-row-hover)";
              }}
              onMouseLeave={(e) => {
                if (!active) e.currentTarget.style.background = "transparent";
              }}
            >
              {t.label}
            </div>
          );
        })}
      </div>

      <div style={{ flex: 1, overflow: "auto", background: "#fff" }}>
        {permTab === "groups" ? (
          <PermissionGrid
            categories={permissionCategories}
            selectedIds={permissionCategoryIds ?? []}
            setPermission={(id, v) =>
              setPermissionCategoryIds((s) => {
                const base = s ?? [];
                return v ? Array.from(new Set([...base, id])) : base.filter((x) => x !== id);
              })
            }
            disabled={disabled || !permsLoaded}
          />
        ) : (
          <ScopeTab
            tabKey={permTab}
            enabled={!!tabPerms[permTab]}
            onToggle={(v) => setTabPerms((s) => ({ ...s, [permTab]: v }))}
            disabled={disabled}
          />
        )}
      </div>

      <div style={{ position: "absolute", right: 0, top: "50%", transform: "translateY(-50%)" }}>
        <button
          style={{
            width: 18,
            height: 40,
            background: "var(--accent)",
            color: "#fff",
            border: "none",
            borderTopLeftRadius: 4,
            borderBottomLeftRadius: 4,
            cursor: "pointer",
            fontSize: 11,
            writingMode: "vertical-rl",
          }}
        >
          帮助
        </button>
      </div>
    </div>
  );
}

interface PermissionGridProps {
  categories: PermissionCategoryVO[];
  selectedIds: number[];
  setPermission: (id: number, v: boolean) => void;
  disabled?: boolean;
}

function PermissionGrid({ categories, selectedIds, setPermission, disabled }: PermissionGridProps) {
  const [filter, setFilter] = useState("");
  const [hovered, setHovered] = useState<string | null>(null);
  const selected = new Set(selectedIds);
  const visibleCategories = categories.filter(
    (c) => !filter || c.sCategoryName.includes(filter) || c.sCategoryCode.includes(filter)
  );
  // 表头全选只反映/操作"当前可见行"，避免过滤态下越权授权或误清。
  const allChecked =
    visibleCategories.length > 0 &&
    visibleCategories.every((c) => selected.has(c.iIncrement));

  return (
    <table
      style={{
        borderCollapse: "collapse",
        width: "100%",
        fontSize: 12,
        tableLayout: "fixed",
      }}
    >
      <colgroup>
        <col style={{ width: 40 }} />
        <col />
      </colgroup>
      <thead>
        <tr style={{ background: "var(--bg-row-zebra)", borderBottom: "1px solid var(--border)" }}>
          <th
            style={{
              padding: "5px 8px",
              borderRight: "1px solid var(--border)",
              textAlign: "center",
            }}
          >
            <PrimCheckbox
              checked={allChecked}
              onChange={(v) => {
                visibleCategories.forEach((c) => setPermission(c.iIncrement, v));
              }}
              disabled={disabled}
            />
          </th>
          <th style={{ padding: "5px 8px", textAlign: "left", fontWeight: 500 }}>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
              权限分类
              <input
                value={filter}
                onChange={(e) => setFilter(e.target.value)}
                placeholder="过滤..."
                style={{
                  height: 20,
                  padding: "0 6px",
                  border: "1px solid var(--border-input)",
                  background: "#fff",
                  fontSize: 11,
                  width: 120,
                  fontFamily: "inherit",
                  outline: "none",
                }}
              />
            </span>
          </th>
        </tr>
      </thead>
      <tbody>
        {visibleCategories.map((c, i) => {
          const isHover = hovered === c.sCategoryCode;
          const checked = selected.has(c.iIncrement);
          return (
            <tr
              key={c.iIncrement}
              onMouseEnter={() => setHovered(c.sCategoryCode)}
              onMouseLeave={() => setHovered(null)}
              onClick={disabled ? undefined : () => setPermission(c.iIncrement, !checked)}
              style={{
                background:
                  isHover && !disabled
                    ? "var(--bg-row-hover)"
                    : checked
                      ? "var(--accent-soft)"
                      : i % 2 === 0
                        ? "#fff"
                        : "var(--bg-row-zebra)",
                cursor: disabled ? "default" : "pointer",
                height: 24,
              }}
            >
              <td
                style={{
                  padding: "3px 0",
                  textAlign: "center",
                  borderRight: "1px solid var(--border)",
                  borderBottom: "1px solid #f0f2f5",
                }}
              >
                <PrimCheckbox
                  checked={checked}
                  onChange={(v) => setPermission(c.iIncrement, v)}
                  disabled={disabled}
                />
              </td>
              <td
                style={{
                  padding: "3px 8px",
                  borderBottom: "1px solid #f0f2f5",
                  color: checked ? "var(--accent-strong)" : "var(--text)",
                  fontWeight: checked ? 500 : 400,
                }}
              >
                {c.sCategoryName}
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

interface ScopeTabProps {
  tabKey: string;
  enabled: boolean;
  onToggle: (v: boolean) => void;
  disabled?: boolean;
}

function ScopeTab({ tabKey, enabled, onToggle, disabled }: ScopeTabProps) {
  const cfg = SCOPE_ITEMS[tabKey];
  const [filter, setFilter] = useState("");
  if (!cfg) return null;

  const filtered = cfg.items.filter((it) => !filter || it.includes(filter));

  return (
    <div style={{ padding: 12 }}>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 12,
          marginBottom: 10,
          paddingBottom: 8,
          borderBottom: "1px solid var(--border)",
        }}
      >
        <PrimCheckbox
          checked={enabled}
          onChange={onToggle}
          disabled={disabled}
          label={`启用${cfg.label}查看权限`}
        />
        <input
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
          placeholder={`筛选${cfg.label}...`}
          style={{
            height: 24,
            padding: "0 8px",
            border: "1px solid var(--border-input)",
            background: "var(--bg-input)",
            fontSize: 12,
            width: 200,
            fontFamily: "inherit",
            outline: "none",
          }}
        />
        <span style={{ flex: 1 }} />
        <span style={{ fontSize: 11, color: "var(--text-muted)" }}>
          共 {cfg.items.length} 个{cfg.label}
        </span>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 6 }}>
        {filtered.map((it) => (
          <label
            key={it}
            style={{
              display: "flex",
              alignItems: "center",
              gap: 6,
              padding: "5px 8px",
              border: "1px solid var(--border)",
              background: enabled ? "#fff" : "var(--bg-disabled)",
              cursor: disabled || !enabled ? "default" : "pointer",
              fontSize: 12,
            }}
          >
            <PrimCheckbox disabled={disabled || !enabled} checked={false} />
            <span style={{ color: enabled ? "var(--text)" : "var(--text-faint)" }}>{it}</span>
          </label>
        ))}
      </div>
    </div>
  );
}
