import { useState } from 'react';
import {
  Avatar,
  Badge,
  Button,
  Input,
  MonoText,
  Tag,
  Select,
  ConfirmDialog,
  Spinner,
  InlineEdit,
  useToast,
} from '@cameleer/design-system';
import {
  useGroups,
  useGroup,
  useCreateGroup,
  useUpdateGroup,
  useDeleteGroup,
  useAssignRoleToGroup,
  useRemoveRoleFromGroup,
  useAddUserToGroup,
  useRemoveUserFromGroup,
  useUsers,
  useRoles,
} from '../../api/queries/admin/rbac';
import styles from './UserManagement.module.css';

const BUILTIN_ADMINS_ID = '00000000-0000-0000-0000-000000000010';

export default function GroupsTab() {
  const [search, setSearch] = useState('');
  const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);
  const [showCreate, setShowCreate] = useState(false);
  const [newGroupName, setNewGroupName] = useState('');
  const [newGroupParentId, setNewGroupParentId] = useState<string>('');
  const [deleteOpen, setDeleteOpen] = useState(false);
  const [addMemberUserId, setAddMemberUserId] = useState<string>('');
  const [addRoleId, setAddRoleId] = useState<string>('');

  const { toast } = useToast();
  const { data: groups = [], isLoading: groupsLoading } = useGroups();
  const { data: selectedGroup, isLoading: detailLoading } = useGroup(selectedGroupId);
  const { data: users = [] } = useUsers();
  const { data: roles = [] } = useRoles();

  const createGroup = useCreateGroup();
  const updateGroup = useUpdateGroup();
  const deleteGroup = useDeleteGroup();
  const assignRoleToGroup = useAssignRoleToGroup();
  const removeRoleFromGroup = useRemoveRoleFromGroup();
  const addUserToGroup = useAddUserToGroup();
  const removeUserFromGroup = useRemoveUserFromGroup();

  const filteredGroups = groups.filter((g) =>
    g.name.toLowerCase().includes(search.toLowerCase())
  );

  const parentOptions = [
    { value: '', label: 'Top-level' },
    ...groups.map((g) => ({ value: g.id, label: g.name })),
  ];

  const parentName = (parentGroupId: string | null) => {
    if (!parentGroupId) return 'Top-level';
    const parent = groups.find((g) => g.id === parentGroupId);
    return parent ? parent.name : parentGroupId;
  };

  const handleCreate = async () => {
    const name = newGroupName.trim();
    if (!name) return;
    try {
      await createGroup.mutateAsync({
        name,
        parentGroupId: newGroupParentId || null,
      });
      toast({ title: 'Group created', variant: 'success' });
      setNewGroupName('');
      setNewGroupParentId('');
      setShowCreate(false);
    } catch {
      toast({ title: 'Failed to create group', variant: 'error' });
    }
  };

  const handleRename = async (newName: string) => {
    if (!selectedGroup) return;
    try {
      await updateGroup.mutateAsync({
        id: selectedGroup.id,
        name: newName,
        parentGroupId: selectedGroup.parentGroupId,
      });
      toast({ title: 'Group renamed', variant: 'success' });
    } catch {
      toast({ title: 'Failed to rename group', variant: 'error' });
    }
  };

  const handleDelete = async () => {
    if (!selectedGroup) return;
    try {
      await deleteGroup.mutateAsync(selectedGroup.id);
      toast({ title: 'Group deleted', variant: 'success' });
      setSelectedGroupId(null);
      setDeleteOpen(false);
    } catch {
      toast({ title: 'Failed to delete group', variant: 'error' });
    }
  };

  const handleAddMember = async () => {
    if (!selectedGroup || !addMemberUserId) return;
    try {
      await addUserToGroup.mutateAsync({
        userId: addMemberUserId,
        groupId: selectedGroup.id,
      });
      toast({ title: 'Member added', variant: 'success' });
      setAddMemberUserId('');
    } catch {
      toast({ title: 'Failed to add member', variant: 'error' });
    }
  };

  const handleRemoveMember = async (userId: string) => {
    if (!selectedGroup) return;
    try {
      await removeUserFromGroup.mutateAsync({ userId, groupId: selectedGroup.id });
      toast({ title: 'Member removed', variant: 'success' });
    } catch {
      toast({ title: 'Failed to remove member', variant: 'error' });
    }
  };

  const handleAddRole = async () => {
    if (!selectedGroup || !addRoleId) return;
    try {
      await assignRoleToGroup.mutateAsync({
        groupId: selectedGroup.id,
        roleId: addRoleId,
      });
      toast({ title: 'Role assigned', variant: 'success' });
      setAddRoleId('');
    } catch {
      toast({ title: 'Failed to assign role', variant: 'error' });
    }
  };

  const handleRemoveRole = async (roleId: string) => {
    if (!selectedGroup) return;
    try {
      await removeRoleFromGroup.mutateAsync({ groupId: selectedGroup.id, roleId });
      toast({ title: 'Role removed', variant: 'success' });
    } catch {
      toast({ title: 'Failed to remove role', variant: 'error' });
    }
  };

  const isBuiltinAdmins = selectedGroup?.id === BUILTIN_ADMINS_ID;

  // Build sets for quick lookup of already-assigned items
  const memberUserIds = new Set((selectedGroup?.members ?? []).map((m) => m.userId));
  const assignedRoleIds = new Set((selectedGroup?.directRoles ?? []).map((r) => r.id));

  const availableUsers = users.filter((u) => !memberUserIds.has(u.userId));
  const availableRoles = roles.filter((r) => !assignedRoleIds.has(r.id));

  return (
    <div className={styles.splitPane}>
      {/* Left pane */}
      <div className={styles.listPane}>
        <div className={styles.listHeader}>
          <Input
            placeholder="Search groups..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            onClear={() => setSearch('')}
          />
          <Button
            size="sm"
            variant="secondary"
            onClick={() => setShowCreate((v) => !v)}
          >
            + Add Group
          </Button>
        </div>

        {showCreate && (
          <div className={styles.createForm}>
            <Input
              placeholder="Group name"
              value={newGroupName}
              onChange={(e) => setNewGroupName(e.target.value)}
            />
            <div style={{ marginTop: 8 }}>
              <Select
                options={parentOptions}
                value={newGroupParentId}
                onChange={(e) => setNewGroupParentId(e.target.value)}
              />
            </div>
            <div className={styles.createFormActions}>
              <Button
                size="sm"
                variant="ghost"
                onClick={() => {
                  setShowCreate(false);
                  setNewGroupName('');
                  setNewGroupParentId('');
                }}
              >
                Cancel
              </Button>
              <Button
                size="sm"
                variant="primary"
                loading={createGroup.isPending}
                onClick={handleCreate}
                disabled={!newGroupName.trim()}
              >
                Create
              </Button>
            </div>
          </div>
        )}

        {groupsLoading ? (
          <Spinner />
        ) : (
          <div className={styles.entityList} role="listbox">
            {filteredGroups.map((group) => {
              const isSelected = group.id === selectedGroupId;
              return (
                <div
                  key={group.id}
                  role="option"
                  aria-selected={isSelected}
                  className={
                    styles.entityItem +
                    (isSelected ? ' ' + styles.entityItemSelected : '')
                  }
                  onClick={() => setSelectedGroupId(group.id)}
                >
                  <Avatar name={group.name} size="sm" />
                  <div className={styles.entityInfo}>
                    <div className={styles.entityName}>{group.name}</div>
                    <div className={styles.entityMeta}>
                      {group.parentGroupId
                        ? `Child of ${parentName(group.parentGroupId)}`
                        : 'Top-level'}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      {/* Right pane */}
      <div className={styles.detailPane}>
        {!selectedGroupId ? (
          <div className={styles.emptyDetail}>Select a group to view details</div>
        ) : detailLoading ? (
          <Spinner />
        ) : selectedGroup ? (
          <div>
            {/* Header */}
            <div className={styles.detailHeader}>
              <Avatar name={selectedGroup.name} size="md" />
              <div style={{ flex: 1, minWidth: 0 }}>
                <InlineEdit
                  value={selectedGroup.name}
                  onSave={handleRename}
                  disabled={isBuiltinAdmins}
                />
                <div className={styles.entityMeta}>
                  {selectedGroup.parentGroupId
                    ? `Child of ${parentName(selectedGroup.parentGroupId)}`
                    : 'Top-level'}
                </div>
              </div>
              <Button
                variant="danger"
                size="sm"
                disabled={isBuiltinAdmins}
                onClick={() => setDeleteOpen(true)}
              >
                Delete
              </Button>
            </div>

            {/* Metadata */}
            <div className={styles.metaGrid}>
              <span className={styles.metaLabel}>Group ID</span>
              <MonoText size="xs">{selectedGroup.id}</MonoText>
              <span className={styles.metaLabel}>Parent</span>
              <span>{parentName(selectedGroup.parentGroupId)}</span>
            </div>

            {/* Members */}
            <div className={styles.sectionTitle}>Members</div>
            <div className={styles.sectionTags}>
              {(selectedGroup.members ?? []).map((member) => (
                <Tag
                  key={member.userId}
                  label={member.displayName}
                  onRemove={() => handleRemoveMember(member.userId)}
                />
              ))}
              {(selectedGroup.members ?? []).length === 0 && (
                <span className={styles.inheritedNote}>No members</span>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
              <Select
                options={[
                  { value: '', label: 'Add member...' },
                  ...availableUsers.map((u) => ({
                    value: u.userId,
                    label: u.displayName,
                  })),
                ]}
                value={addMemberUserId}
                onChange={(e) => setAddMemberUserId(e.target.value)}
              />
              <Button
                size="sm"
                variant="secondary"
                onClick={handleAddMember}
                disabled={!addMemberUserId || addUserToGroup.isPending}
              >
                Add
              </Button>
            </div>

            {/* Assigned roles */}
            <div className={styles.sectionTitle}>Assigned Roles</div>
            <div className={styles.sectionTags}>
              {(selectedGroup.directRoles ?? []).map((role) => (
                <Badge
                  key={role.id}
                  label={role.name}
                  variant="outlined"
                  onRemove={() => handleRemoveRole(role.id)}
                />
              ))}
              {(selectedGroup.directRoles ?? []).length === 0 && (
                <span className={styles.inheritedNote}>No roles assigned</span>
              )}
            </div>
            {(selectedGroup.effectiveRoles ?? []).length >
              (selectedGroup.directRoles ?? []).length && (
              <div className={styles.inheritedNote}>
                +
                {(selectedGroup.effectiveRoles ?? []).length -
                  (selectedGroup.directRoles ?? []).length}{' '}
                inherited role(s)
              </div>
            )}
            <div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
              <Select
                options={[
                  { value: '', label: 'Assign role...' },
                  ...availableRoles.map((r) => ({
                    value: r.id,
                    label: r.name,
                  })),
                ]}
                value={addRoleId}
                onChange={(e) => setAddRoleId(e.target.value)}
              />
              <Button
                size="sm"
                variant="secondary"
                onClick={handleAddRole}
                disabled={!addRoleId || assignRoleToGroup.isPending}
              >
                Add
              </Button>
            </div>
          </div>
        ) : null}
      </div>

      {/* Delete confirmation */}
      <ConfirmDialog
        open={deleteOpen}
        onClose={() => setDeleteOpen(false)}
        onConfirm={handleDelete}
        title="Delete Group"
        message={`Delete group "${selectedGroup?.name}"? This action cannot be undone.`}
        confirmText="DELETE"
        variant="danger"
        loading={deleteGroup.isPending}
      />
    </div>
  );
}
