"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Alert,
  Button,
  Card,
  Descriptions,
  Divider,
  Drawer,
  Form,
  Input,
  message,
  Modal,
  Popconfirm,
  Select,
  Space,
  Spin,
  Table,
  Tag,
  Typography,
} from "antd";
import type { ColumnsType, TablePaginationConfig } from "antd/es/table";
import {
  CheckOutlined,
  EditOutlined,
  EyeOutlined,
  PlusOutlined,
  ReloadOutlined,
  SettingOutlined,
  StopOutlined,
} from "@ant-design/icons";

import { apiClient } from "@/lib/api/client";
import { fetchEmployees, type Employee as EmployeeRecord } from "@/lib/api/employees";
import { useAuth } from "@/lib/hooks/use-auth";

const { Title, Paragraph, Text } = Typography;

type PermissionMetadata = {
  apis?: string[];
  menus?: string[];
};

type Permission = {
  id: number;
  name: string;
  description?: string;
  metadata?: PermissionMetadata;
};

type Role = {
  id: number;
  name: string;
  description?: string;
  is_default?: boolean;
  permissions?: Permission[];
};

type EmployeeLink = {
  id: number;
  name: string;
  email: string;
  department_id?: string;
  department_name?: string;
  avatar_url?: string;
};

type UserRecord = {
  id: number;
  name: string;
  email: string;
  status: string;
  roles: Role[];
  default_role_id?: number;
  default_role?: Role;
  last_login_at?: string;
  employee_id?: number | null;
  employee_link_status?: "pending" | "linked" | "failed";
  employee?: EmployeeLink | null;
};

type PaginatedResponse<T> = {
  items: T[];
  total: number;
  page: number;
  page_size: number;
};

const statusColors: Record<string, string> = {
  active: "green",
  suspended: "red",
  inactive: "orange",
};

const linkStatusColors: Record<string, string> = {
  linked: "green",
  failed: "red",
  pending: "default",
};

type ManageRolesModalProps = {
  open: boolean;
  user?: UserRecord;
  roles: Role[];
  onClose: () => void;
  onSaved: () => void;
};

type RoleEditorState = {
  open: boolean;
  role?: Role;
};

type EmployeeLinkModalState = {
  open: boolean;
  user?: UserRecord;
};

function ManageRolesModal({ open, user, roles, onClose, onSaved }: ManageRolesModalProps) {
  const [selectedRoleIds, setSelectedRoleIds] = useState<number[]>([]);
  const [defaultRoleId, setDefaultRoleId] = useState<number | undefined>(undefined);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (user) {
      const ids = (user.roles || []).map((r) => r.id);
      setSelectedRoleIds(ids);
      const inferredDefault = user.default_role_id ?? user.default_role?.id ?? ids[0];
      setDefaultRoleId(inferredDefault);
    }
  }, [user]);

  const handleSave = async () => {
    if (!user) return;
    if (selectedRoleIds.length === 0) {
      message.warning("Select at least one role");
      return;
    }
    if (defaultRoleId && !selectedRoleIds.includes(defaultRoleId)) {
      message.warning("Default role must be one of the selected roles");
      return;
    }
    setSaving(true);
    try {
      await apiClient.post(`/users/${user.id}/roles`, {
        role_ids: selectedRoleIds,
        default_role_id: defaultRoleId ?? selectedRoleIds[0],
      });
      message.success("Roles updated");
      onSaved();
      onClose();
    } catch (err) {
      message.error("Failed to update roles");
    } finally {
      setSaving(false);
    }
  };

  return (
    <Modal
      title="Assign Roles"
      open={open}
      onCancel={onClose}
      onOk={handleSave}
      okButtonProps={{ loading: saving }}
      okText="Save"
      destroyOnClose
    >
      <Space direction="vertical" size={12} style={{ width: "100%" }}>
        <div>
          <Text strong>Roles</Text>
          <Select<number[]>
            mode="multiple"
            style={{ width: "100%", marginTop: 8 }}
            placeholder="Select roles"
            value={selectedRoleIds}
            onChange={(ids: number[]) => {
              setSelectedRoleIds(ids);
              if (ids.length > 0 && (defaultRoleId === undefined || !ids.includes(defaultRoleId))) {
                setDefaultRoleId(ids[0]);
              }
            }}
            options={roles.map((role) => ({
              label: (
                <Space>
                  <span>{role.name}</span>
                  {role.is_default ? <Tag color="blue">default</Tag> : null}
                </Space>
              ),
              value: role.id,
            }))}
          />
        </div>
        <div>
          <Text strong>Default role</Text>
          <Select<number>
            style={{ width: "100%", marginTop: 8 }}
            placeholder="Pick default role"
            value={defaultRoleId}
            onChange={(val) => setDefaultRoleId(val)}
            options={selectedRoleIds.map((id) => {
              const role = roles.find((r) => r.id === id);
              return { value: id, label: role ? role.name : `Role ${id}` };
            })}
          />
        </div>
      </Space>
    </Modal>
  );
}

function RoleEditorModal({
  state,
  permissions,
  onClose,
  onSaved,
}: {
  state: RoleEditorState;
  permissions: Permission[];
  onClose: () => void;
  onSaved: () => void;
}) {
  const [form] = Form.useForm();
  const [saving, setSaving] = useState(false);
  const role = state.role;

  useEffect(() => {
    if (state.open) {
      form.setFieldsValue({
        name: role?.name,
        description: role?.description,
        is_default: (role?.is_default ?? false).toString(),
        permission_ids: role?.permissions?.map((p) => p.id) ?? [],
      });
    } else {
      form.resetFields();
    }
  }, [form, role, state.open]);

  const handleSubmit = async () => {
    const payload = await form.validateFields();
    const normalized = {
      ...payload,
      is_default: payload.is_default === "true" || payload.is_default === true,
    };
    setSaving(true);
    try {
      if (role) {
        await apiClient.put(`/roles/${role.id}`, normalized);
        message.success("Role updated");
      } else {
        await apiClient.post("/roles", normalized);
        message.success("Role created");
      }
      onSaved();
      onClose();
    } catch (err) {
      message.error("Failed to save role");
    } finally {
      setSaving(false);
    }
  };

  return (
    <Modal
      title={role ? `Edit Role: ${role.name}` : "Create Role"}
      open={state.open}
      onCancel={onClose}
      onOk={handleSubmit}
      okButtonProps={{ loading: saving }}
      destroyOnClose
      width={640}
    >
      <Form layout="vertical" form={form}>
        <Form.Item name="name" label="Name" rules={[{ required: true, message: "Role name is required" }]}>
          <Input placeholder="e.g., admin" />
        </Form.Item>
        <Form.Item name="description" label="Description">
          <Input.TextArea rows={2} placeholder="What does this role do?" />
        </Form.Item>
        <Form.Item name="is_default" label="Default role">
          <Select
            options={[
              { label: "No (manual assignment only)", value: "false" },
              { label: "Yes (auto-assign on first SSO login)", value: "true" },
            ]}
          />
        </Form.Item>
        <Form.Item name="permission_ids" label="Permissions" rules={[{ required: true, message: "Select permissions" }]}>
          <Select
            mode="multiple"
            placeholder="Select permissions"
            options={permissions.map((p) => ({
              value: p.id,
              label: p.name,
              title: p.description,
            }))}
          />
        </Form.Item>
      </Form>
    </Modal>
  );
}

export default function UsersPage() {
  const { hasPermission } = useAuth();
  const [data, setData] = useState<UserRecord[]>([]);
  const [total, setTotal] = useState(0);
  const [pagination, setPagination] = useState<TablePaginationConfig>({ current: 1, pageSize: 10 });
  const [loading, setLoading] = useState(false);
  const [filters, setFilters] = useState<{ query?: string; status?: string; roleId?: number }>({});
  const [roles, setRoles] = useState<Role[]>([]);
  const [permissions, setPermissions] = useState<Permission[]>([]);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [drawerLoading, setDrawerLoading] = useState(false);
  const [selectedUser, setSelectedUser] = useState<UserRecord | undefined>(undefined);
  const [roleModalOpen, setRoleModalOpen] = useState(false);
  const [roleEditorState, setRoleEditorState] = useState<RoleEditorState>({ open: false });
  const [employees, setEmployees] = useState<EmployeeRecord[]>([]);
  const [employeesLoading, setEmployeesLoading] = useState(false);
  const [employeeLinkState, setEmployeeLinkState] = useState<EmployeeLinkModalState>({ open: false });
  const [employeeLinkForm] = Form.useForm<{ employee_id: number; reason: string }>();
  const [employeeLinkSaving, setEmployeeLinkSaving] = useState(false);

  const canManageUsers = hasPermission("auth:manage_users");

  const openCreateRole = () => setRoleEditorState({ open: true, role: undefined });
  const openEditRole = (role: Role) => setRoleEditorState({ open: true, role });

  const handleDeleteRole = async (role: Role) => {
    try {
      await apiClient.delete(`/roles/${role.id}`);
      message.success("Role deleted");
      fetchRoles();
      refreshUsers();
    } catch (err) {
      message.error("Failed to delete role");
    }
  };

  const fetchRoles = useCallback(async () => {
    try {
      const res = await apiClient.get("/roles", { params: { page: 1, page_size: 100 } });
      const payload = res.data?.data as PaginatedResponse<Role> | undefined;
      if (payload?.items) {
        setRoles(payload.items);
      }
    } catch (err) {
      message.error("Failed to load roles");
    }
  }, []);

  const fetchPermissions = useCallback(async () => {
    try {
      const res = await apiClient.get("/permissions");
      const payload = res.data?.data as Permission[] | undefined;
      if (payload) {
        setPermissions(payload);
      }
    } catch (err) {
      message.error("Failed to load permissions");
    }
  }, []);

  const fetchEmployeeList = useCallback(async () => {
    if (!canManageUsers) return;
    setEmployeesLoading(true);
    try {
      const data = await fetchEmployees();
      setEmployees(data ?? []);
    } catch (err) {
      message.error("Failed to load employees");
    } finally {
      setEmployeesLoading(false);
    }
  }, [canManageUsers]);

  const fetchUsers = useCallback(
    async (page: number, pageSize: number) => {
      setLoading(true);
      try {
        const response = await apiClient.get("/users", {
          params: {
            page,
            page_size: pageSize,
            query: filters.query || undefined,
            status: filters.status || undefined,
            role_id: filters.roleId || undefined,
          },
        });
        const payload = response.data?.data as PaginatedResponse<UserRecord> | undefined;
        if (payload) {
          setData(payload.items ?? []);
          setTotal(payload.total ?? 0);
        }
      } catch (err) {
        message.error("Failed to load users");
      } finally {
        setLoading(false);
      }
    },
    [filters.query, filters.roleId, filters.status],
  );

  useEffect(() => {
    fetchUsers(pagination.current ?? 1, pagination.pageSize ?? 10);
  }, [fetchUsers, pagination]);

  useEffect(() => {
    fetchRoles();
    fetchPermissions();
  }, [fetchPermissions, fetchRoles]);

  useEffect(() => {
    fetchEmployeeList();
  }, [fetchEmployeeList]);

  const refreshUsers = useCallback(() => {
    fetchUsers(pagination.current ?? 1, pagination.pageSize ?? 10);
  }, [fetchUsers, pagination]);

  const selectedLinkTarget = Form.useWatch("employee_id", employeeLinkForm);
  const employeeDirectoryByID = useMemo(() => {
    const index = new Map<number, EmployeeRecord>();
    employees.forEach((employee) => {
      index.set(employee.id, employee);
    });
    return index;
  }, [employees]);
  const linkTargetEmployee = useMemo(
    () => employees.find((employee) => employee.id === selectedLinkTarget),
    [employees, selectedLinkTarget],
  );
  const linkSourceUser = employeeLinkState.user;
  const linkEmailMatch = useMemo(() => {
    if (!linkSourceUser || !linkTargetEmployee?.email) {
      return false;
    }
    return linkSourceUser.email.trim().toLowerCase() === linkTargetEmployee.email.trim().toLowerCase();
  }, [linkSourceUser, linkTargetEmployee]);

  const openEmployeeRepair = (user: UserRecord) => {
    setEmployeeLinkState({ open: true, user });
    employeeLinkForm.setFieldsValue({
      employee_id: user.employee_id ?? undefined,
      reason: "",
    });
  };

  const closeEmployeeRepair = () => {
    setEmployeeLinkState({ open: false, user: undefined });
    employeeLinkForm.resetFields();
  };

  const handleEmployeeRepair = async () => {
    const user = employeeLinkState.user;
    if (!user) return;

    const values = await employeeLinkForm.validateFields();
    setEmployeeLinkSaving(true);
    try {
      await apiClient.post(`/users/${user.id}/link-employee`, values);
      message.success(user.employee_id ? "Employee link updated" : "Employee linked");
      closeEmployeeRepair();
      refreshUsers();
      if (selectedUser?.id === user.id) {
        await handleView(user);
      }
    } catch (err) {
      const apiMessage =
        err && typeof err === "object" && "response" in err
          ? ((err as { response?: { data?: { message?: string } } }).response?.data?.message ?? null)
          : null;
      message.error(apiMessage || "Failed to repair employee link");
    } finally {
      setEmployeeLinkSaving(false);
    }
  };

  const handleView = async (record: UserRecord) => {
    setDrawerLoading(true);
    try {
      const res = await apiClient.get(`/users/${record.id}`);
      setSelectedUser(res.data?.data as UserRecord);
      setDrawerOpen(true);
    } catch (err) {
      message.error("Failed to load user");
    } finally {
      setDrawerLoading(false);
    }
  };

  const handleStatusToggle = async (record: UserRecord) => {
    const nextStatus = record.status === "active" ? "suspended" : "active";
    try {
      await apiClient.put(`/users/${record.id}`, { status: nextStatus });
      message.success(`User ${nextStatus === "active" ? "activated" : "disabled"}`);
      refreshUsers();
      if (selectedUser?.id === record.id) {
        await handleView(record);
      }
    } catch (err) {
      message.error("Failed to update status");
    }
  };

  const resolveDepartmentLabel = useCallback(
    (employee?: EmployeeLink | null) => {
      if (!employee) {
        return "—";
      }
      const directoryEmployee = employeeDirectoryByID.get(employee.id);
      return (
        directoryEmployee?.department_name ||
        employee.department_name ||
        directoryEmployee?.department_id ||
        employee.department_id ||
        "—"
      );
    },
    [employeeDirectoryByID],
  );

  const columns: ColumnsType<UserRecord> = [
    {
      title: "Name",
      dataIndex: "name",
      key: "name",
      width: 240,
      render: (value, record) => (
        <Space direction="vertical" size={0}>
          <span style={{ fontWeight: 500 }}>{value || record.email}</span>
          <Paragraph type="secondary" style={{ margin: 0 }}>
            {record.email}
          </Paragraph>
        </Space>
      ),
    },
    {
      title: "Status",
      dataIndex: "status",
      key: "status",
      render: (status) => <Tag color={statusColors[status] ?? "default"}>{status}</Tag>,
      width: 140,
    },
    {
      title: "Roles",
      dataIndex: "roles",
      key: "roles",
      width: 220,
      render: (list: Role[] = []) => (
        <Space wrap>
          {list.length === 0 ? <Tag>viewer</Tag> : list.map((role) => <Tag key={role.id}>{role.name}</Tag>)}
        </Space>
      ),
    },
    {
      title: "Employee",
      dataIndex: "employee",
      key: "employee",
      render: (_: unknown, record) => {
        if (record.employee) {
          return (
            <Space direction="vertical" size={0}>
              <Text strong>{record.employee.name || record.employee.email}</Text>
              <Text type="secondary" style={{ fontSize: 12 }}>
                {record.employee.email}
              </Text>
            </Space>
          );
        }
        return <Tag color="default">Unlinked</Tag>;
      },
      width: 240,
    },
    {
      title: "Link Status",
      dataIndex: "employee_link_status",
      key: "employee_link_status",
      render: (status: UserRecord["employee_link_status"]) => {
        const value = status || "pending";
        return <Tag color={linkStatusColors[value] ?? "default"}>{value}</Tag>;
      },
      width: 140,
    },
    {
      title: "Department",
      dataIndex: "employee",
      key: "department",
      render: (_: unknown, record) => (
        <Text style={{ wordBreak: "break-word" }}>{resolveDepartmentLabel(record.employee)}</Text>
      ),
      width: 220,
    },
    {
      title: "Last Login",
      dataIndex: "last_login_at",
      key: "last_login",
      render: (value: string | undefined) => value ?? "—",
      width: 200,
    },
    {
      title: "Actions",
      key: "actions",
      render: (_, record) => (
        <Space size="small" style={{ whiteSpace: "nowrap" }}>
          <Button size="small" icon={<EyeOutlined />} onClick={() => handleView(record)}>
            View
          </Button>
          <Button size="small" disabled={!canManageUsers} onClick={() => openEmployeeRepair(record)}>
            {record.employee_id ? "Relink" : "Repair"}
          </Button>
          <Button
            size="small"
            icon={<EditOutlined />}
            disabled={!canManageUsers}
            onClick={() => {
              setSelectedUser(record);
              setRoleModalOpen(true);
            }}
          >
            Edit Roles
          </Button>
          <Button
            size="small"
            icon={record.status === "active" ? <StopOutlined /> : <CheckOutlined />}
            disabled={!canManageUsers}
            onClick={() => handleStatusToggle(record)}
          >
            {record.status === "active" ? "Disable" : "Activate"}
          </Button>
        </Space>
      ),
      width: 440,
    },
  ];

  const employeeColumns: ColumnsType<EmployeeRecord> = [
    {
      title: "Name",
      dataIndex: "name",
      key: "name",
      render: (value, record) => (
        <Space direction="vertical" size={0}>
          <span style={{ fontWeight: 500 }}>{value || record.email}</span>
          <Paragraph type="secondary" style={{ margin: 0 }}>
            {record.email}
          </Paragraph>
        </Space>
      ),
    },
    {
      title: "Department",
      dataIndex: "department_name",
      key: "department",
      render: (_, record) => record.department_name || record.department_id || "—",
      width: 200,
    },
    {
      title: "Status",
      dataIndex: "status",
      key: "status",
      render: (status) => <Tag color={statusColors[status] ?? "default"}>{status}</Tag>,
      width: 140,
    },
    {
      title: "First Login",
      dataIndex: "first_login_at",
      key: "first_login_at",
      render: (value: string | null | undefined) => (value ? <Tag color="green">Yes</Tag> : <Tag>Not yet</Tag>),
      width: 140,
    },
    {
      title: "Association",
      dataIndex: "employee_link_status",
      key: "employee_link_status",
      render: (status: EmployeeRecord["employee_link_status"]) => {
        const value = status || "pending";
        return <Tag color={linkStatusColors[value] ?? "default"}>{value}</Tag>;
      },
      width: 160,
    },
  ];

  const permissionPreview = useMemo(() => {
    if (!selectedUser) return [];
    const map = new Map<string, PermissionMetadata>();
    selectedUser.roles?.forEach((role) => {
      role.permissions?.forEach((perm) => {
        const existing = map.get(perm.name) || { apis: [], menus: [] };
        const merged = {
          apis: Array.from(new Set([...(existing.apis ?? []), ...(perm.metadata?.apis ?? [])])),
          menus: Array.from(new Set([...(existing.menus ?? []), ...(perm.metadata?.menus ?? [])])),
        };
        map.set(perm.name, merged);
      });
    });
    return Array.from(map.entries()).map(([name, meta]) => ({ name, meta }));
  }, [selectedUser]);

  const handleFilterChange = (key: "query" | "status" | "roleId", value?: string | number) => {
    setFilters((prev) => ({ ...prev, [key]: value }));
    setPagination((prev) => ({ ...prev, current: 1 }));
  };

  return (
    <Space direction="vertical" size={24} style={{ width: "100%" }}>
      <Card>
        <Space direction="vertical" size={16} style={{ width: "100%" }}>
          <div>
            <Title level={3} style={{ marginBottom: 0 }}>
              User Access
            </Title>
            <Paragraph type="secondary" style={{ marginBottom: 0, maxWidth: 780 }}>
              Assign roles, review user accounts, and check employee linking from separate sections below.
            </Paragraph>
          </div>
          <Space wrap>
            <Button href="#roles-section">Roles</Button>
            <Button href="#users-section">User accounts</Button>
            <Button href="#employees-section">Employee linking</Button>
          </Space>
        </Space>
      </Card>

      <Card
        id="roles-section"
        title="Roles"
        size="small"
        style={{ scrollMarginTop: 24 }}
        extra={
          <Button type="primary" icon={<PlusOutlined />} onClick={openCreateRole} disabled={!canManageUsers}>
            Create Role
          </Button>
        }
      >
        <Paragraph type="secondary" style={{ marginTop: -4 }}>
          Define permission bundles once, then reuse them across users and SSO defaults.
        </Paragraph>
        <Table<Role>
          rowKey={(r) => String(r.id)}
          size="small"
          pagination={false}
          dataSource={roles}
          columns={[
            { title: "Name", dataIndex: "name", key: "name" },
            { title: "Description", dataIndex: "description", key: "description", ellipsis: true },
            {
              title: "Default",
              dataIndex: "is_default",
              key: "is_default",
              render: (val) => (val ? <Tag color="blue">Default</Tag> : "—"),
              width: 120,
            },
            {
              title: "Permissions",
              key: "permissions",
              render: (_, record) => record.permissions?.length ?? 0,
              width: 140,
            },
            {
              title: "Actions",
              key: "actions",
              width: 220,
              render: (_, record) => (
                <Space>
                  <Button size="small" onClick={() => openEditRole(record)} disabled={!canManageUsers}>
                    Edit
                  </Button>
                  <Popconfirm
                    title="Delete role?"
                    okText="Delete"
                    cancelText="Cancel"
                    okButtonProps={{ danger: true }}
                    onConfirm={() => handleDeleteRole(record)}
                    disabled={!canManageUsers || record.is_default}
                  >
                    <Button size="small" danger disabled={!canManageUsers || record.is_default}>
                      Delete
                    </Button>
                  </Popconfirm>
                </Space>
              ),
            },
          ]}
        />
      </Card>

      <Card
        id="users-section"
        title="User accounts"
        size="small"
        style={{ scrollMarginTop: 24 }}
        extra={
          <Button icon={<ReloadOutlined />} onClick={() => refreshUsers()}>
            Refresh
          </Button>
        }
      >
        <Space direction="vertical" size={16} style={{ width: "100%" }}>
          <Paragraph type="secondary" style={{ marginBottom: 0 }}>
            Search SSO-provisioned users, filter by status or role, and open the detail drawer for permissions or
            status changes.
          </Paragraph>
          <Space wrap>
            <Input.Search
              allowClear
              placeholder="Search name or email"
              onSearch={(value) => handleFilterChange("query", value)}
              style={{ width: 260 }}
            />
            <Select
              allowClear
              placeholder="Status"
              style={{ width: 140 }}
              options={[
                { value: "active", label: "Active" },
                { value: "inactive", label: "Inactive" },
                { value: "suspended", label: "Suspended" },
              ]}
              onChange={(val) => handleFilterChange("status", val || undefined)}
            />
            <Select
              allowClear
              placeholder="Role"
              style={{ width: 160 }}
              options={roles.map((r) => ({ value: r.id, label: r.name }))}
              onChange={(val) => handleFilterChange("roleId", val || undefined)}
            />
          </Space>
          <div style={{ width: "100%", overflowX: "auto" }}>
            <Table<UserRecord>
              rowKey={(record) => String(record.id)}
              loading={loading}
              columns={columns}
              dataSource={data}
              scroll={{ x: "max-content" }}
              pagination={{
                ...pagination,
                total,
                showSizeChanger: true,
                onChange: (page, pageSize) => setPagination({ current: page, pageSize }),
              }}
              onChange={(pager: TablePaginationConfig) => {
                setPagination(pager);
              }}
            />
          </div>
        </Space>
      </Card>

      <Card
        id="employees-section"
        title="Employee linking"
        size="small"
        style={{ scrollMarginTop: 24 }}
        extra={
          <Button icon={<ReloadOutlined />} onClick={fetchEmployeeList} disabled={!canManageUsers}>
            Refresh
          </Button>
        }
      >
        <Paragraph type="secondary" style={{ marginTop: -4 }}>
          Track which employees are linked to users, whether linking succeeded, and where manual follow-up is needed.
        </Paragraph>
        <div style={{ width: "100%", overflowX: "auto" }}>
          <Table<EmployeeRecord>
            rowKey={(record) => String(record.id)}
            loading={employeesLoading}
            pagination={{ pageSize: 10 }}
            dataSource={employees}
            columns={employeeColumns}
            scroll={{ x: "max-content" }}
          />
        </div>
      </Card>

      <Drawer
        title="User details"
        width={720}
        onClose={() => setDrawerOpen(false)}
        open={drawerOpen}
        destroyOnClose
        extra={
          <Space>
            <Button
              icon={<SettingOutlined />}
              disabled={!canManageUsers || !selectedUser}
              onClick={() => setRoleModalOpen(true)}
            >
              Edit Roles
            </Button>
            {selectedUser ? (
              <Button
                icon={selectedUser.status === "active" ? <StopOutlined /> : <CheckOutlined />}
                disabled={!canManageUsers}
                onClick={() => handleStatusToggle(selectedUser)}
              >
                {selectedUser.status === "active" ? "Disable" : "Activate"}
              </Button>
            ) : null}
          </Space>
        }
      >
        {drawerLoading ? (
          <Spin tip="Loading user…" />
        ) : (
          selectedUser && (
            <Space direction="vertical" size={16} style={{ width: "100%" }}>
              <Descriptions column={2} bordered size="small">
                <Descriptions.Item label="Name">{selectedUser.name || "—"}</Descriptions.Item>
                <Descriptions.Item label="Email">{selectedUser.email}</Descriptions.Item>
                <Descriptions.Item label="Status">
                  <Tag color={statusColors[selectedUser.status] ?? "default"}>{selectedUser.status}</Tag>
                </Descriptions.Item>
                <Descriptions.Item label="Default Role">
                  {selectedUser.default_role?.name || selectedUser.default_role_id || "—"}
                </Descriptions.Item>
                <Descriptions.Item label="Last Login">{selectedUser.last_login_at || "—"}</Descriptions.Item>
                <Descriptions.Item label="Link Status">
                  <Tag color={linkStatusColors[selectedUser.employee_link_status || "pending"] ?? "default"}>
                    {selectedUser.employee_link_status || "pending"}
                  </Tag>
                </Descriptions.Item>
                <Descriptions.Item label="Employee">
                  {selectedUser.employee ? (
                    <Space>
                      <span>{selectedUser.employee.name || selectedUser.employee.email}</span>
                      <Tag color={selectedUser.employee_link_status === "linked" ? "green" : "default"}>
                        {selectedUser.employee_link_status === "linked" ? "Linked" : "Needs review"}
                      </Tag>
                    </Space>
                  ) : (
                    "Unlinked"
                  )}
                </Descriptions.Item>
                <Descriptions.Item label="Department">
                  {resolveDepartmentLabel(selectedUser.employee)}
                </Descriptions.Item>
                <Descriptions.Item label="Roles" span={2}>
                  <Space wrap>
                    {selectedUser.roles?.length
                      ? selectedUser.roles.map((role) => (
                          <Tag key={role.id} color={role.is_default ? "blue" : undefined}>
                            {role.name}
                          </Tag>
                        ))
                      : "viewer"}
                  </Space>
                </Descriptions.Item>
              </Descriptions>
              {canManageUsers ? (
                <Card size="small" title="Employee repair">
                  <Space direction="vertical" size={12} style={{ width: "100%" }}>
                    <Text type="secondary">
                      Use the existing employee directory to repair or relink the SSO user. Email mismatches are allowed
                      only with an explicit reason and will be audited.
                    </Text>
                    <Button onClick={() => openEmployeeRepair(selectedUser)} style={{ width: "fit-content" }}>
                      {selectedUser.employee_id ? "Relink employee" : "Repair link"}
                    </Button>
                  </Space>
                </Card>
              ) : null}
              <Divider style={{ margin: "8px 0" }}>Permission Matrix</Divider>
              <Space direction="vertical" style={{ width: "100%" }}>
                {permissionPreview.length === 0 ? (
                  <Text type="secondary">No permissions assigned</Text>
                ) : (
                  permissionPreview.map(({ name, meta }) => (
                    <Card key={name} size="small" title={name}>
                      <Space direction="vertical" style={{ width: "100%" }}>
                        <div>
                          <Text strong>APIs:</Text>{" "}
                          {meta.apis?.length ? meta.apis.map((api) => <Tag key={api}>{api}</Tag>) : <Text type="secondary">—</Text>}
                        </div>
                        <div>
                          <Text strong>Menus:</Text>{" "}
                          {meta.menus?.length ? meta.menus.map((menu) => <Tag key={menu}>{menu}</Tag>) : <Text type="secondary">—</Text>}
                        </div>
                      </Space>
                    </Card>
                  ))
                )}
              </Space>
            </Space>
          )
        )}
      </Drawer>

      <ManageRolesModal
        open={roleModalOpen}
        user={selectedUser}
        roles={roles}
        onClose={() => setRoleModalOpen(false)}
        onSaved={() => {
          refreshUsers();
          if (selectedUser) {
            handleView(selectedUser);
          }
        }}
      />

      <RoleEditorModal
        state={roleEditorState}
        permissions={permissions}
        onClose={() => setRoleEditorState({ open: false })}
        onSaved={() => {
          fetchRoles();
          fetchPermissions();
          refreshUsers();
          setRoleModalOpen(false);
        }}
      />

      <Modal
        title={employeeLinkState.user?.employee_id ? "Repair or relink employee" : "Repair employee link"}
        open={employeeLinkState.open}
        onCancel={closeEmployeeRepair}
        onOk={handleEmployeeRepair}
        okText={employeeLinkState.user?.employee_id ? "Save relink" : "Save link"}
        okButtonProps={{ loading: employeeLinkSaving }}
        destroyOnClose
      >
        <Space direction="vertical" size={16} style={{ width: "100%" }}>
          <Text type="secondary">
            Pick a Feishu-synced employee record for this SSO user. The backend keeps this as the single repair path
            and writes audit details for every repair or relink.
          </Text>
          {employeeLinkState.user ? (
            <Descriptions column={1} bordered size="small">
              <Descriptions.Item label="User">{employeeLinkState.user.name || employeeLinkState.user.email}</Descriptions.Item>
              <Descriptions.Item label="User email">{employeeLinkState.user.email}</Descriptions.Item>
              <Descriptions.Item label="Current status">
                <Tag color={linkStatusColors[employeeLinkState.user.employee_link_status || "pending"] ?? "default"}>
                  {employeeLinkState.user.employee_link_status || "pending"}
                </Tag>
              </Descriptions.Item>
              <Descriptions.Item label="Current employee">
                {employeeLinkState.user.employee?.name || employeeLinkState.user.employee?.email || "Unlinked"}
              </Descriptions.Item>
            </Descriptions>
          ) : null}
          <Form layout="vertical" form={employeeLinkForm}>
            <Form.Item
              name="employee_id"
              label="Target employee"
              rules={[{ required: true, message: "Select an employee" }]}
            >
              <Select
                showSearch
                loading={employeesLoading}
                placeholder="Search Feishu-synced employee"
                optionFilterProp="label"
                options={employees.map((employee) => ({
                  value: employee.id,
                  label: `${employee.name || employee.email} · ${employee.email}`,
                  title: employee.department_name || employee.department_id || undefined,
                }))}
              />
            </Form.Item>
            {linkTargetEmployee ? (
              <Card size="small">
                <Space direction="vertical" size={4} style={{ width: "100%" }}>
                  <Text strong>{linkTargetEmployee.name || linkTargetEmployee.email}</Text>
                  <Text type="secondary">{linkTargetEmployee.email}</Text>
                  <Text type="secondary">{linkTargetEmployee.department_name || linkTargetEmployee.department_id || "No department"}</Text>
                </Space>
              </Card>
            ) : null}
            {linkTargetEmployee && !linkEmailMatch ? (
              <Alert
                type="warning"
                showIcon
                message="Email mismatch requires explicit repair reason"
                description={`User ${employeeLinkState.user?.email || "—"} does not match employee ${linkTargetEmployee.email}. The relink will be allowed but audited as an override.`}
              />
            ) : null}
            <Form.Item
              name="reason"
              label="Reason"
              extra="Required for repair and relink. This value is stored in the audit trail."
              rules={[{ required: true, message: "Explain why this link is being repaired" }]}
            >
              <Input.TextArea
                rows={3}
                placeholder="Examples: rehired employee with new email, stale auto-link, contractor converted to employee"
              />
            </Form.Item>
          </Form>
        </Space>
      </Modal>
    </Space>
  );
}
