/* global React, Icon, Button, Field, Dialog, PageHead, useToast, Check, ALL_MODULES, FilterBar, Pager, PAGE_SIZES, useSortableTable */

const { useState, useMemo } = React;

const PERM_COLS = [
  { key: "create", label: "新增" },
  { key: "edit",   label: "編輯" },
  { key: "view",   label: "檢視" },
  { key: "delete", label: "刪除" },
];

// Build full 26-module matrix from sparse AUTH_ROLE_PERMISSIONS format
const buildMatrix = (roleKey, rolePermissions) => {
  const sparse = rolePermissions[roleKey] || [];
  const map = {};
  sparse.forEach(g => g.modules.forEach(m => { map[m.name] = { ...m.perms }; }));
  return ALL_MODULES.map(cat => ({
    category: cat.category,
    modules: cat.modules.map(name => ({
      name,
      perms: map[name] || { create: false, edit: false, view: false, delete: false },
    })),
  }));
};

// Convert full matrix back to sparse (only modules with at least one true perm)
const toSparse = (matrix) =>
  matrix
    .map(g => ({
      category: g.category,
      modules: g.modules.filter(m => m.perms.create || m.perms.edit || m.perms.view || m.perms.delete),
    }))
    .filter(g => g.modules.length > 0);

// ── Permission table ─────────────────────────────────────────────────────────
const PermTable = ({ matrix, onChange }) => {
  const toggleCell = (gi, mi, col) => {
    const next = matrix.map((g, gIdx) => {
      if (gIdx !== gi) return g;
      return {
        ...g,
        modules: g.modules.map((m, mIdx) => {
          if (mIdx !== mi) return m;
          const np = { ...m.perms };
          if (col === "view") {
            const hasOther = np.create || np.edit || np.delete;
            if (hasOther) return m;
            np.view = !np.view;
          } else {
            np[col] = !np[col];
            if (np.create || np.edit || np.delete) np.view = true;
          }
          return { ...m, perms: np };
        }),
      };
    });
    onChange(next);
  };

  const toggleCategory = (gi) => {
    const group = matrix[gi];
    const allChecked = group.modules.every(m => PERM_COLS.every(c => m.perms[c.key]));
    const next = matrix.map((g, gIdx) =>
      gIdx !== gi ? g : {
        ...g,
        modules: g.modules.map(m => ({
          ...m,
          perms: allChecked
            ? { create: false, edit: false, view: false, delete: false }
            : { create: true, edit: true, view: true, delete: true },
        })),
      }
    );
    onChange(next);
  };

  return (
    <table style={{ width: "100%", borderCollapse: "separate", borderSpacing: 0 }}>
      <thead>
        <tr>
          <th style={{ padding: "6px 10px", borderBottom: "1px solid var(--border-1)" }} />
          {PERM_COLS.map(c => (
            <th key={c.key} style={{ padding: "6px 10px", fontSize: "var(--fs-11)", fontWeight: "var(--fw-semibold)", color: "var(--fg-2)", textAlign: "center", width: 64, borderBottom: "1px solid var(--border-1)" }}>
              {c.label}
            </th>
          ))}
        </tr>
      </thead>
      <tbody>
        {matrix.flatMap((group, gi) => [
          <tr key={`cat-${gi}`}>
            <td colSpan={5} style={{
              padding: gi === 0 ? "8px 10px 4px" : "12px 10px 4px",
              ...(gi > 0 ? { borderTop: "1px solid var(--border-1)" } : {}),
            }}>
              <label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer", userSelect: "none" }}>
                <Check
                  checked={group.modules.every(m => PERM_COLS.every(c => m.perms[c.key]))}
                  onChange={() => toggleCategory(gi)}
                />
                <span style={{ fontSize: "var(--fs-11)", fontWeight: "var(--fw-semibold)", color: "var(--fg-4)", textTransform: "uppercase", letterSpacing: "0.05em" }}>
                  {group.category}
                </span>
              </label>
            </td>
          </tr>,
          ...group.modules.map((mod, mi) => {
            const viewLocked = mod.perms.create || mod.perms.edit || mod.perms.delete;
            return (
              <tr key={`${gi}-${mi}`}>
                <td style={{ padding: "6px 10px 6px 32px", color: "var(--fg-1)", fontSize: "var(--fs-13)" }}>{mod.name}</td>
                {PERM_COLS.map(c => {
                  const isViewLocked = c.key === "view" && viewLocked;
                  return (
                    <td key={c.key} style={{ padding: "6px 10px", textAlign: "center", width: 64 }}>
                      {isViewLocked
                        ? <Check checked={true} readOnly />
                        : <Check checked={mod.perms[c.key]} onChange={() => toggleCell(gi, mi, c.key)} />
                      }
                    </td>
                  );
                })}
              </tr>
            );
          }),
        ])}
      </tbody>
    </table>
  );
};

// ── RoleForm (L2 新增 / 編輯) ────────────────────────────────────────────────
const RoleForm = ({ mode, initial, rolePermissions, onCancel, onSave }) => {
  const isEdit = mode === "edit";

  const emptyMatrix = ALL_MODULES.map(cat => ({
    category: cat.category,
    modules: cat.modules.map(name => ({
      name,
      perms: { create: false, edit: false, view: false, delete: false },
    })),
  }));

  const [label,  setLabel]  = useState(initial?.label || "");
  const [matrix, setMatrix] = useState(() =>
    isEdit ? buildMatrix(initial.key, rolePermissions) : emptyMatrix
  );
  const [errors, setErrors] = useState({});

  const savedLabel  = React.useRef(initial?.label  || "");
  const savedMatrix = React.useRef(isEdit ? buildMatrix(initial.key, rolePermissions) : emptyMatrix);
  const isDirty = useDirtyTracker(
    { label: savedLabel.current, matrix: savedMatrix.current },
    { label, matrix }
  );

  const canSave = label.trim();

  const handleSave = () => {
    if (!label.trim()) { setErrors({ label: "請輸入角色名稱" }); return; }
    onSave({ label: label.trim(), permissions: toSparse(matrix) });
  };

  return (
    <>
      <PageHead
        crumbs={[
          { label: "帳號與權限" },
          { label: "角色存取權限設定", onClick: onCancel },
          { label: isEdit ? initial.label : "新增", current: true },
        ]}
        title={isEdit ? initial.label : "新增角色"}
        dirty={isDirty}
        actions={<>
          <Button variant="default" onClick={onCancel}>取消</Button>
          <Button variant="primary" onClick={handleSave} disabled={!canSave}>
            {isEdit ? "儲存變更" : "確認建立"}
          </Button>
        </>}
      />

      {/* Card 1：基本資訊 */}
      <div className="card">
        <div className="card__body">
          <div style={{ display: "flex", alignItems: "flex-start", gap: 12 }}>
            <span style={{ fontSize: "var(--fs-13)", fontWeight: "var(--fw-medium)", color: "var(--fg-1)", flexShrink: 0, paddingTop: 7 }}>
              角色名稱<span style={{ color: "var(--danger)", marginLeft: 2 }}>*</span>
            </span>
            <div style={{ flex: 1 }}>
              <Field
                value={label}
                onChange={e => { setLabel(e.target.value); setErrors(er => ({ ...er, label: undefined })); }}
                placeholder="請輸入角色名稱"
                error={!!errors.label}
                style={{ width: "100%" }}
              />
              {errors.label && <div style={{ fontSize: "var(--fs-12)", color: "var(--danger)", marginTop: 4 }}>{errors.label}</div>}
            </div>
          </div>
        </div>
      </div>

      {/* Card 2：功能權限設定 */}
      <div className="card" style={{ marginTop: 16 }}>
        <div className="card__head">
          <div className="card__title">功能權限設定</div>
        </div>
        <div className="tbl-wrap">
          <PermTable matrix={matrix} onChange={setMatrix} />
        </div>
      </div>
    </>
  );
};

// ── ConfirmDialog ─────────────────────────────────────────────────────────────
const ConfirmDialog = ({ title, body, cancelLabel = "取消", confirmLabel, variant = "primary", onClose, onConfirm }) => (
  <Dialog
    open
    title={title}
    onClose={onClose}
    footer={<>
      <Button variant="text" onClick={onClose}>{cancelLabel}</Button>
      {confirmLabel && <Button variant={variant} onClick={onConfirm}>{confirmLabel}</Button>}
    </>}
  >
    <div style={{ lineHeight: 1.6 }}>{body}</div>
  </Dialog>
);

// ── RoleList (L1) ─────────────────────────────────────────────────────────────
const RoleList = ({ roles, roleLabels, rolePermissions, isSysAdmin, users, onAddRole, onUpdateRole, onDeleteRole, sectionLabel, titleLabel }) => {
  const { push: showToast } = useToast();
  const [screen,   setScreen]   = useState(null);
  const [dialog,   setDialog]   = useState(null);
  const [q,        setQ]        = useState("");
  const [page,     setPage]     = useState(1);
  const [pageSize, setPageSize] = useState(PAGE_SIZES[0]);
  const { SortHead, applySortTo } = useSortableTable("label", "asc");

  const countModules = (roleKey) => {
    const perms = rolePermissions[roleKey] || [];
    return perms.reduce((n, g) => n + g.modules.length, 0);
  };

  const handleDelete = (roleKey) => {
    const name  = roleLabels[roleKey] || roleKey;
    const count = (users || []).filter(u => u.roles && u.roles.includes(roleKey)).length;
    if (count > 0) {
      setDialog({ type: "blocked", name, count });
    } else {
      setDialog({ type: "confirm", key: roleKey, name });
    }
  };

  const filtered = roles.filter(rk =>
    !q || (roleLabels[rk] || rk).includes(q)
  );
  const sorted = useMemo(() => applySortTo(filtered, (rk, key) =>
    key === "count" ? countModules(rk) : (roleLabels[rk] || rk)
  ), [filtered, roleLabels, rolePermissions, applySortTo]);
  const paged = sorted.slice((page - 1) * pageSize, page * pageSize);

  // ── Screen: Add ─────────────────────────────────────────────────────────────
  if (screen === "add") {
    return (
      <RoleForm
        mode="add"
        initial={null}
        rolePermissions={rolePermissions}
        onCancel={() => setScreen(null)}
        onSave={({ label, permissions }) => {
          const key = "ROLE_" + Date.now();
          onAddRole(key, label, permissions);
          setScreen(null);
          showToast({ kind: "success", msg: "角色已建立" });
        }}
      />
    );
  }

  // ── Screen: Edit ─────────────────────────────────────────────────────────────
  if (screen?.type === "edit") {
    const roleKey = screen.roleKey;
    return (
      <RoleForm
        mode="edit"
        initial={{ key: roleKey, label: roleLabels[roleKey] }}
        rolePermissions={rolePermissions}
        onCancel={() => setScreen(null)}
        onSave={({ label, permissions }) => {
          onUpdateRole(roleKey, label, permissions);
          setScreen(null);
          showToast({ kind: "success", msg: "角色設定已更新" });
        }}
      />
    );
  }

  // ── Screen: List ─────────────────────────────────────────────────────────────
  return (
    <>
      <PageHead
        section={sectionLabel}
        title={titleLabel}
        actions={isSysAdmin && (
          <Button variant="primary" icon="plus" onClick={() => setScreen("add")}>
            新增角色
          </Button>
        )}
      />

      <FilterBar
        filters={[
          { type: "search", placeholder: "搜尋角色名稱…", value: q, onChange: v => { setQ(v); setPage(1); } },
        ]}
      />

      <div className="card">
        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <th><SortHead colKey="label" label="角色名稱" /></th>
                <th className="num" style={{ width: 120 }}><SortHead colKey="count" label="功能項目數" /></th>
                {isSysAdmin && <th className="center" style={{ width: 160 }}>功能</th>}
              </tr>
            </thead>
            <tbody>
              {paged.length === 0 ? (
                <tr><td colSpan={isSysAdmin ? 3 : 2} style={{ textAlign: "center", color: "var(--fg-4)", padding: "40px 0" }}>尚無角色</td></tr>
              ) : paged.map(roleKey => (
                <tr key={roleKey}>
                  <td style={{ fontWeight: "var(--fw-medium)" }}>{roleLabels[roleKey]}</td>
                  <td className="num">{countModules(roleKey)} 個</td>
                  {isSysAdmin && (
                    <td className="center">
                      <div className="actions">
                        <button className="row-act" onClick={() => setScreen({ type: "edit", roleKey })}>編輯</button>
                        <button className="row-act row-act--danger" onClick={() => handleDelete(roleKey)}>刪除</button>
                      </div>
                    </td>
                  )}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <Pager total={filtered.length} page={page} pageSize={pageSize}
          onPageChange={setPage} onSizeChange={s => { setPageSize(s); setPage(1); }} />
      </div>

      {dialog?.type === "blocked" && (
        <ConfirmDialog
          title="無法刪除角色"
          body={`有 ${dialog.count} 位使用者仍指派了「${dialog.name}」，請先在使用者管理中移除後再刪除。`}
          cancelLabel="確定"
          onClose={() => setDialog(null)}
        />
      )}
      {dialog?.type === "confirm" && (
        <ConfirmDialog
          title="刪除角色"
          body={`確定要刪除「${dialog.name}」嗎？此動作無法還原。`}
          confirmLabel="刪除"
          variant="danger"
          onClose={() => setDialog(null)}
          onConfirm={() => {
            onDeleteRole(dialog.key);
            setDialog(null);
            showToast({ kind: "success", msg: "角色已刪除" });
          }}
        />
      )}
    </>
  );
};

Object.assign(window, { RoleList });
