import { useState, useMemo, useEffect } from 'react';
import {
  Avatar,
  Badge,
  Button,
  Input,
  Select,
  MonoText,
  SectionHeader,
  Tag,
  InlineEdit,
  MultiSelect,
  ConfirmDialog,
  AlertDialog,
  SplitPane,
  EntityList,
  Spinner,
  useToast,
} from '@cameleer/design-system';
import {
  useGroups,
  useGroup,
  useCreateGroup,
  useUpdateGroup,
  useDeleteGroup,
  useAssignRoleToGroup,
  useRemoveRoleFromGroup,
  useAddUserToGroup,
  useRemoveUserFromGroup,
  useUsers,
  useRoles,
} from '../../api/queries/admin/rbac';
import type { GroupDetail } from '../../api/queries/admin/rbac';
import { PageLoader } from '../../components/PageLoader';
import styles from './UserManagement.module.css';
import sectionStyles from '../../styles/section-card.module.css';

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

export default function GroupsTab({ highlightId, onHighlightConsumed }: { highlightId?: string | null; onHighlightConsumed?: () => void }) {
  const { toast } = useToast();
  const { data: groups = [], isLoading: groupsLoading } = useGroups();
  const { data: users = [] } = useUsers();
  const { data: roles = [] } = useRoles();

  const [search, setSearch] = useState('');
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [creating, setCreating] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<GroupDetail | null>(null);
  const [removeRoleTarget, setRemoveRoleTarget] = useState<string | null>(null);

  // Auto-select highlighted item from cmd-k navigation
  useEffect(() => {
    if (highlightId && groups) {
      const match = groups.find((g) => g.id === highlightId);
      if (match) {
        setSelectedId(match.id);
        onHighlightConsumed?.();
      }
    }
  }, [highlightId, groups]); // eslint-disable-line react-hooks/exhaustive-deps

  // Create form state
  const [newName, setNewName] = useState('');
  const [newParent, setNewParent] = useState('');

  // Detail query
  const { data: selectedGroup, isLoading: detailLoading } = useGroup(selectedId);

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

  const filtered = useMemo(() => {
    if (!search) return groups;
    const q = search.toLowerCase();
    return groups.filter((g) => g.name.toLowerCase().includes(q));
  }, [groups, search]);

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

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

  const duplicateGroupName =
    newName.trim() !== '' &&
    groups.some(
      (g) => g.name.toLowerCase() === newName.trim().toLowerCase(),
    );

  // Derived data for the detail pane
  const children = selectedGroup?.childGroups ?? [];
  const members = selectedGroup?.members ?? [];
  const parentGroup = selectedGroup?.parentGroupId
    ? groups.find((g) => g.id === selectedGroup.parentGroupId)
    : null;

  const memberUserIds = new Set(members.map((m) => m.userId));
  const assignedRoleIds = new Set(
    (selectedGroup?.directRoles ?? []).map((r) => r.id),
  );

  const availableRoles = roles
    .filter((r) => !assignedRoleIds.has(r.id))
    .map((r) => ({ value: r.id, label: r.name }));

  const availableMembers = users
    .filter((u) => !memberUserIds.has(u.userId))
    .map((u) => ({ value: u.userId, label: u.displayName }));

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

  async function handleCreate() {
    if (!newName.trim()) return;
    try {
      await createGroup.mutateAsync({
        name: newName.trim(),
        parentGroupId: newParent || null,
      });
      toast({ title: 'Group created', description: newName.trim(), variant: 'success' });
      setCreating(false);
      setNewName('');
      setNewParent('');
    } catch {
      toast({ title: 'Failed to create group', variant: 'error', duration: 86_400_000 });
    }
  }

  async function handleDelete() {
    if (!deleteTarget) return;
    try {
      await deleteGroup.mutateAsync(deleteTarget.id);
      toast({
        title: 'Group deleted',
        description: deleteTarget.name,
        variant: 'warning',
      });
      if (selectedId === deleteTarget.id) setSelectedId(null);
      setDeleteTarget(null);
    } catch {
      toast({ title: 'Failed to delete group', variant: 'error', duration: 86_400_000 });
      setDeleteTarget(null);
    }
  }

  async function handleRename(newNameVal: string) {
    if (!selectedGroup) return;
    try {
      await updateGroup.mutateAsync({
        id: selectedGroup.id,
        name: newNameVal,
        parentGroupId: selectedGroup.parentGroupId,
      });
      toast({ title: 'Group renamed', variant: 'success' });
    } catch {
      toast({ title: 'Failed to rename group', variant: 'error', duration: 86_400_000 });
    }
  }

  async function handleRemoveMember(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', duration: 86_400_000 });
    }
  }

  async function handleAddMembers(userIds: string[]) {
    if (!selectedGroup) return;
    for (const userId of userIds) {
      try {
        await addUserToGroup.mutateAsync({
          userId,
          groupId: selectedGroup.id,
        });
        toast({ title: 'Member added', variant: 'success' });
      } catch {
        toast({ title: 'Failed to add member', variant: 'error', duration: 86_400_000 });
      }
    }
  }

  async function handleAddRoles(roleIds: string[]) {
    if (!selectedGroup) return;
    for (const roleId of roleIds) {
      try {
        await assignRoleToGroup.mutateAsync({
          groupId: selectedGroup.id,
          roleId,
        });
        toast({ title: 'Role assigned', variant: 'success' });
      } catch {
        toast({ title: 'Failed to assign role', variant: 'error', duration: 86_400_000 });
      }
    }
  }

  async function handleRemoveRole(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', duration: 86_400_000 });
    }
  }

  if (groupsLoading) return <PageLoader />;

  return (
    <>
      <SplitPane
        list={
          <>
            {creating && (
              <div className={styles.createForm}>
                <Input
                  placeholder="Group name *"
                  value={newName}
                  onChange={(e) => setNewName(e.target.value)}
                />
                {duplicateGroupName && (
                  <span className={styles.errorText}>
                    Group name already exists
                  </span>
                )}
                <Select
                  options={parentOptions}
                  value={newParent}
                  onChange={(e) => setNewParent(e.target.value)}
                />
                <div className={styles.createFormActions}>
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => setCreating(false)}
                  >
                    Cancel
                  </Button>
                  <Button
                    size="sm"
                    variant="primary"
                    onClick={handleCreate}
                    loading={createGroup.isPending}
                    disabled={!newName.trim() || duplicateGroupName}
                  >
                    Create
                  </Button>
                </div>
              </div>
            )}

            <EntityList
              items={filtered}
              renderItem={(group) => {
                const groupChildren = groups.filter(
                  (g) => g.parentGroupId === group.id,
                );
                const groupParent = group.parentGroupId
                  ? groups.find((g) => g.id === group.parentGroupId)
                  : null;
                return (
                  <>
                    <Avatar name={group.name} size="sm" />
                    <div className={styles.entityInfo}>
                      <div className={styles.entityName}>{group.name}</div>
                      <div className={styles.entityMeta}>
                        {groupParent
                          ? `Child of ${groupParent.name}`
                          : 'Top-level'}
                        {' \u00b7 '}
                        {groupChildren.length} children
                        {' \u00b7 '}
                        {(group.members ?? []).length} members
                      </div>
                      <div className={styles.entityTags}>
                        {(group.directRoles ?? []).map((r) => (
                          <Badge key={r.id} label={r.name} color="warning" />
                        ))}
                      </div>
                    </div>
                  </>
                );
              }}
              getItemId={(group) => group.id}
              selectedId={selectedId ?? undefined}
              onSelect={setSelectedId}
              searchPlaceholder="Search groups..."
              onSearch={setSearch}
              addLabel="+ Add group"
              onAdd={() => setCreating(true)}
              emptyMessage="No groups match your search"
            />
          </>
        }
        detail={
          selectedId && detailLoading ? (
            <Spinner size="md" />
          ) : selectedGroup ? (
            <>
              <div className={styles.detailHeader}>
                <Avatar name={selectedGroup.name} size="lg" />
                <div className={styles.detailHeaderInfo}>
                  <div className={styles.detailName}>
                    {isBuiltinAdmins ? (
                      selectedGroup.name
                    ) : (
                      <InlineEdit
                        value={selectedGroup.name}
                        onSave={handleRename}
                      />
                    )}
                  </div>
                  <div className={styles.detailEmail}>
                    {parentGroup
                      ? `${parentGroup.name} > ${selectedGroup.name}`
                      : 'Top-level group'}
                    {isBuiltinAdmins && ' (built-in)'}
                  </div>
                </div>
                <Button
                  size="sm"
                  variant="danger"
                  onClick={() => setDeleteTarget(selectedGroup)}
                  disabled={isBuiltinAdmins}
                >
                  Delete
                </Button>
              </div>

              <div className={styles.metaGrid}>
                <span className={styles.metaLabel}>ID</span>
                <MonoText size="xs">{selectedGroup.id}</MonoText>
              </div>

              {parentGroup && (
                <>
                  <SectionHeader>Member of</SectionHeader>
                  <div className={styles.sectionTags}>
                    <Tag label={parentGroup.name} color="auto" />
                  </div>
                </>
              )}

              <div className={sectionStyles.section}>
                <SectionHeader>Members (direct)</SectionHeader>
                <div className={styles.sectionTags}>
                  {members.map((u) => (
                    <Tag
                      key={u.userId}
                      label={u.displayName}
                      color="auto"
                      onRemove={() => handleRemoveMember(u.userId)}
                    />
                  ))}
                  {members.length === 0 && (
                    <span className={styles.inheritedNote}>(no members)</span>
                  )}
                  <MultiSelect
                    options={availableMembers}
                    value={[]}
                    onChange={handleAddMembers}
                    placeholder="+ Add"
                  />
                </div>
                {children.length > 0 && (
                  <span className={styles.inheritedNote}>
                    + all members of {children.map((c) => c.name).join(', ')}
                  </span>
                )}
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>Child groups</SectionHeader>
                <div className={styles.sectionTags}>
                  {children.map((c) => (
                    <Tag key={c.id} label={c.name} color="success" />
                  ))}
                  {children.length === 0 && (
                    <span className={styles.inheritedNote}>
                      (no child groups)
                    </span>
                  )}
                </div>
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>Assigned roles</SectionHeader>
                <div className={styles.sectionTags}>
                  {(selectedGroup.directRoles ?? []).map((r) => (
                    <Tag
                      key={r.id}
                      label={r.name}
                      color="warning"
                      onRemove={() => {
                        if (members.length > 0) {
                          setRemoveRoleTarget(r.id);
                        } else {
                          handleRemoveRole(r.id);
                        }
                      }}
                    />
                  ))}
                  {(selectedGroup.directRoles ?? []).length === 0 && (
                    <span className={styles.inheritedNote}>(no roles)</span>
                  )}
                  <MultiSelect
                    options={availableRoles}
                    value={[]}
                    onChange={handleAddRoles}
                    placeholder="+ Add"
                  />
                </div>
              </div>
            </>
          ) : null
        }
        emptyMessage="Select a group to view details"
      />

      <ConfirmDialog
        open={deleteTarget !== null}
        onClose={() => setDeleteTarget(null)}
        onConfirm={handleDelete}
        message={`Delete group "${deleteTarget?.name}"? This cannot be undone.`}
        confirmText={deleteTarget?.name ?? ''}
        loading={deleteGroup.isPending}
      />
      <AlertDialog
        open={removeRoleTarget !== null}
        onClose={() => setRemoveRoleTarget(null)}
        onConfirm={() => {
          if (removeRoleTarget && selectedGroup) {
            handleRemoveRole(removeRoleTarget);
          }
          setRemoveRoleTarget(null);
        }}
        title="Remove role from group"
        description={`Removing this role will affect ${members.length} member(s) who inherit it. Continue?`}
        confirmLabel="Remove"
        variant="warning"
      />
    </>
  );
}
