import { useState, useMemo, useEffect } from 'react';
import {
  Avatar,
  Badge,
  Button,
  Input,
  MonoText,
  SectionHeader,
  Tag,
  InlineEdit,
  RadioGroup,
  RadioItem,
  InfoCallout,
  MultiSelect,
  ConfirmDialog,
  AlertDialog,
  SplitPane,
  EntityList,
  useToast,
} from '@cameleer/design-system';
import {
  useUsers,
  useCreateUser,
  useUpdateUser,
  useDeleteUser,
  useAssignRoleToUser,
  useRemoveRoleFromUser,
  useAddUserToGroup,
  useRemoveUserFromGroup,
  useSetPassword,
  useGroups,
  useRoles,
} from '../../api/queries/admin/rbac';
import type { UserDetail } from '../../api/queries/admin/rbac';
import { useAuthStore } from '../../auth/auth-store';
import { PageLoader } from '../../components/PageLoader';
import styles from './UserManagement.module.css';
import sectionStyles from '../../styles/section-card.module.css';

export default function UsersTab({ highlightId, onHighlightConsumed }: { highlightId?: string | null; onHighlightConsumed?: () => void }) {
  const { toast } = useToast();
  const { data: users, isLoading } = useUsers();
  const { data: allGroups } = useGroups();
  const { data: allRoles } = useRoles();
  const currentUsername = useAuthStore((s) => s.username);

  const [search, setSearch] = useState('');
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [creating, setCreating] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<UserDetail | null>(null);
  const [removeGroupTarget, setRemoveGroupTarget] = useState<string | null>(null);
  const [removeRoleTarget, setRemoveRoleTarget] = useState<{ id: string; name: string } | null>(null);

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

  // Create form state
  const [newUsername, setNewUsername] = useState('');
  const [newDisplay, setNewDisplay] = useState('');
  const [newEmail, setNewEmail] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [newPasswordConfirm, setNewPasswordConfirm] = useState('');
  const [newProvider, setNewProvider] = useState<'local' | 'oidc'>('local');

  const passwordMismatch = newPassword.length > 0 && newPasswordConfirm.length > 0 && newPassword !== newPasswordConfirm;

  // Password reset state
  const [resettingPassword, setResettingPassword] = useState(false);
  const [newPw, setNewPw] = useState('');

  // Mutations
  const createUser = useCreateUser();
  const updateUser = useUpdateUser();
  const deleteUser = useDeleteUser();
  const assignRole = useAssignRoleToUser();
  const removeRole = useRemoveRoleFromUser();
  const addToGroup = useAddUserToGroup();
  const removeFromGroup = useRemoveUserFromGroup();
  const setPassword = useSetPassword();

  const userList = users ?? [];

  const filtered = useMemo(() => {
    if (!search) return userList;
    const q = search.toLowerCase();
    return userList.filter(
      (u) =>
        u.displayName.toLowerCase().includes(q) ||
        (u.email ?? '').toLowerCase().includes(q) ||
        u.userId.toLowerCase().includes(q),
    );
  }, [userList, search]);

  const selected = userList.find((u) => u.userId === selectedId) ?? null;

  const isSelf =
    currentUsername != null &&
    selected != null &&
    selected.displayName === currentUsername;

  const duplicateUsername =
    newUsername.trim() !== '' &&
    userList.some(
      (u) => u.displayName.toLowerCase() === newUsername.trim().toLowerCase(),
    );

  // Derived data for detail pane
  const directGroupIds = new Set(selected?.directGroups.map((g) => g.id) ?? []);
  const directRoleIds = new Set(selected?.directRoles.map((r) => r.id) ?? []);
  const inheritedRoles =
    selected?.effectiveRoles.filter((r) => !directRoleIds.has(r.id)) ?? [];

  const availableGroups = (allGroups ?? [])
    .filter((g) => !directGroupIds.has(g.id))
    .map((g) => ({ value: g.id, label: g.name }));

  const availableRoles = (allRoles ?? [])
    .filter((r) => !directRoleIds.has(r.id))
    .map((r) => ({ value: r.id, label: r.name }));

  function handleCreate() {
    if (!newUsername.trim()) return;
    if (newProvider === 'local' && !newPassword.trim()) return;
    createUser.mutate(
      {
        username: newUsername.trim(),
        displayName: newDisplay.trim() || undefined,
        email: newEmail.trim() || undefined,
        password: newProvider === 'local' ? newPassword : undefined,
      },
      {
        onSuccess: () => {
          toast({
            title: 'User created',
            description: newDisplay.trim() || newUsername.trim(),
            variant: 'success',
          });
          setCreating(false);
          setNewUsername('');
          setNewDisplay('');
          setNewEmail('');
          setNewPassword('');
          setNewPasswordConfirm('');
          setNewProvider('local');
        },
        onError: (err: unknown) => {
          const message = err instanceof Error ? err.message : 'Unknown error';
          toast({ title: 'Failed to create user', description: message, variant: 'error', duration: 86_400_000 });
        },
      },
    );
  }

  function handleDelete() {
    if (!deleteTarget) return;
    deleteUser.mutate(deleteTarget.userId, {
      onSuccess: () => {
        toast({
          title: 'User deleted',
          description: deleteTarget.displayName,
          variant: 'warning',
        });
        if (selectedId === deleteTarget.userId) setSelectedId(null);
        setDeleteTarget(null);
      },
      onError: () => {
        toast({ title: 'Failed to delete user', variant: 'error', duration: 86_400_000 });
        setDeleteTarget(null);
      },
    });
  }

  function handleResetPassword() {
    if (!selected || !newPw.trim()) return;
    setPassword.mutate(
      { userId: selected.userId, password: newPw },
      {
        onSuccess: () => {
          toast({
            title: 'Password updated',
            description: selected.displayName,
            variant: 'success',
          });
          setResettingPassword(false);
          setNewPw('');
        },
        onError: () => {
          toast({ title: 'Failed to update password', variant: 'error', duration: 86_400_000 });
        },
      },
    );
  }

  function getUserGroupPath(user: UserDetail): string {
    if (user.directGroups.length === 0) return 'no groups';
    return user.directGroups.map((g) => g.name).join(', ');
  }

  if (isLoading) return <PageLoader />;

  return (
    <>
      <SplitPane
        list={
          <>
            {creating && (
              <div className={styles.createForm}>
                <RadioGroup
                  name="provider"
                  value={newProvider}
                  onChange={(v) => setNewProvider(v as 'local' | 'oidc')}
                  orientation="horizontal"
                >
                  <RadioItem value="local" label="Local" />
                  <RadioItem value="oidc" label="OIDC" />
                </RadioGroup>
                <div className={styles.createFormRow}>
                  <Input
                    placeholder="Username *"
                    value={newUsername}
                    onChange={(e) => setNewUsername(e.target.value)}
                  />
                  <Input
                    placeholder="Display name"
                    value={newDisplay}
                    onChange={(e) => setNewDisplay(e.target.value)}
                  />
                </div>
                {duplicateUsername && (
                  <span className={styles.errorText}>
                    Username already exists
                  </span>
                )}
                <Input
                  placeholder="Email"
                  value={newEmail}
                  onChange={(e) => setNewEmail(e.target.value)}
                />
                {newProvider === 'local' && (
                  <>
                    <Input
                      placeholder="Password *"
                      type="password"
                      value={newPassword}
                      onChange={(e) => setNewPassword(e.target.value)}
                    />
                    <Input
                      placeholder="Confirm Password *"
                      type="password"
                      value={newPasswordConfirm}
                      onChange={(e) => setNewPasswordConfirm(e.target.value)}
                    />
                    {passwordMismatch && (
                      <span className={styles.errorText}>Passwords do not match</span>
                    )}
                    <span className={styles.hintText}>Min 12 chars, 3 of 4: uppercase, lowercase, number, special</span>
                  </>
                )}
                {newProvider === 'oidc' && (
                  <InfoCallout variant="amber">
                    OIDC users authenticate via the configured identity provider.
                    Pre-register to assign roles/groups before their first login.
                  </InfoCallout>
                )}
                <div className={styles.createFormActions}>
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => { setCreating(false); setNewPasswordConfirm(''); }}
                  >
                    Cancel
                  </Button>
                  <Button
                    size="sm"
                    variant="primary"
                    onClick={handleCreate}
                    loading={createUser.isPending}
                    disabled={
                      !newUsername.trim() ||
                      (newProvider === 'local' && !newPassword.trim()) ||
                      duplicateUsername ||
                      passwordMismatch
                    }
                  >
                    Create
                  </Button>
                </div>
              </div>
            )}

            <EntityList
              items={filtered}
              renderItem={(user) => (
                <>
                  <Avatar name={user.displayName} size="sm" />
                  <div className={styles.entityInfo}>
                    <div className={styles.entityName}>
                      {user.displayName}
                      {user.provider !== 'local' && (
                        <Badge
                          label={user.provider}
                          color="running"
                          variant="outlined"
                          className={styles.providerBadge}
                        />
                      )}
                    </div>
                    <div className={styles.entityMeta}>
                      {user.email || user.userId} &middot;{' '}
                      {getUserGroupPath(user)}
                    </div>
                    <div className={styles.entityTags}>
                      {user.directRoles.map((r) => (
                        <Badge key={r.id} label={r.name} color="warning" />
                      ))}
                      {user.directGroups.map((g) => (
                        <Badge key={g.id} label={g.name} color="success" />
                      ))}
                    </div>
                  </div>
                </>
              )}
              getItemId={(user) => user.userId}
              selectedId={selectedId ?? undefined}
              onSelect={(id) => {
                setSelectedId(id);
                setResettingPassword(false);
              }}
              searchPlaceholder="Search users..."
              onSearch={setSearch}
              addLabel="+ Add user"
              onAdd={() => setCreating(true)}
              emptyMessage="No users match your search"
            />
          </>
        }
        detail={
          selected ? (
            <>
              <div className={styles.detailHeader}>
                <Avatar name={selected.displayName} size="lg" />
                <div className={styles.detailHeaderInfo}>
                  <div className={styles.detailName}>
                    <InlineEdit
                      value={selected.displayName}
                      onSave={(v) =>
                        updateUser.mutate(
                          { userId: selected.userId, displayName: v },
                          {
                            onSuccess: () =>
                              toast({
                                title: 'Display name updated',
                                variant: 'success',
                              }),
                            onError: () =>
                              toast({
                                title: 'Failed to update name',
                                variant: 'error',
                                duration: 86_400_000,
                              }),
                          },
                        )
                      }
                    />
                  </div>
                  <div className={styles.detailEmail}>
                    {selected.email || selected.userId}
                  </div>
                </div>
                <Button
                  size="sm"
                  variant="danger"
                  onClick={() => setDeleteTarget(selected)}
                  disabled={isSelf}
                >
                  Delete
                </Button>
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>Status</SectionHeader>
                <div className={styles.sectionTags}>
                  <Tag label="Active" color="success" />
                </div>

                <div className={styles.metaGrid}>
                  <span className={styles.metaLabel}>ID</span>
                  <MonoText size="xs">{selected.userId}</MonoText>
                  <span className={styles.metaLabel}>Created</span>
                  <span className={styles.metaValue}>
                    {new Date(selected.createdAt).toLocaleDateString()}
                  </span>
                  <span className={styles.metaLabel}>Provider</span>
                  <span className={styles.metaValue}>{selected.provider}</span>
                </div>
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>Security</SectionHeader>
                <div className={styles.securitySection}>
                {selected.provider === 'local' ? (
                  <>
                    <div className={styles.securityRow}>
                      <span className={styles.metaLabel}>Password</span>
                      <span className={styles.passwordDots}>
                        ••••••••
                      </span>
                      {!resettingPassword && (
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => {
                            setResettingPassword(true);
                            setNewPw('');
                          }}
                        >
                          Reset password
                        </Button>
                      )}
                    </div>
                    {resettingPassword && (
                      <div className={styles.resetForm}>
                        <Input
                          placeholder="New password"
                          type="password"
                          value={newPw}
                          onChange={(e) => setNewPw(e.target.value)}
                          className={styles.resetInput}
                        />
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => setResettingPassword(false)}
                        >
                          Cancel
                        </Button>
                        <Button
                          size="sm"
                          variant="primary"
                          onClick={handleResetPassword}
                          loading={setPassword.isPending}
                          disabled={!newPw.trim()}
                        >
                          Set
                        </Button>
                      </div>
                    )}
                  </>
                ) : (
                  <>
                    <div className={styles.securityRow}>
                      <span className={styles.metaLabel}>Authentication</span>
                      <span className={styles.metaValue}>
                        OIDC ({selected.provider})
                      </span>
                    </div>
                    <InfoCallout variant="amber">
                      Password managed by the identity provider.
                    </InfoCallout>
                  </>
                )}
                </div>
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>Group membership (direct only)</SectionHeader>
                <div className={styles.sectionTags}>
                  {selected.directGroups.map((g) => (
                    <Tag
                      key={g.id}
                      label={g.name}
                      color="success"
                      onRemove={() => {
                        removeFromGroup.mutate(
                          { userId: selected.userId, groupId: g.id },
                          {
                            onSuccess: () =>
                              toast({ title: 'Group removed', variant: 'success' }),
                            onError: () =>
                              toast({
                                title: 'Failed to remove group',
                                variant: 'error',
                                duration: 86_400_000,
                              }),
                          },
                        );
                      }}
                    />
                  ))}
                  {selected.directGroups.length === 0 && (
                    <span className={styles.inheritedNote}>(no groups)</span>
                  )}
                  <MultiSelect
                    options={availableGroups}
                    value={[]}
                    onChange={(ids) => {
                      for (const groupId of ids) {
                        addToGroup.mutate(
                          { userId: selected.userId, groupId },
                          {
                            onSuccess: () =>
                              toast({ title: 'Added to group', variant: 'success' }),
                            onError: () =>
                              toast({
                                title: 'Failed to add group',
                                variant: 'error',
                                duration: 86_400_000,
                              }),
                          },
                        );
                      }
                    }}
                    placeholder="+ Add"
                  />
                </div>
              </div>

              <div className={sectionStyles.section}>
                <SectionHeader>
                  Effective roles (direct + inherited)
                </SectionHeader>
                <div className={styles.sectionTags}>
                  {selected.directRoles.map((r) => (
                    <Tag
                      key={r.id}
                      label={r.name}
                      color="warning"
                      onRemove={() => setRemoveRoleTarget(r)}
                    />
                  ))}
                  {inheritedRoles.map((r) => (
                    <Badge
                      key={r.id}
                      label={`${r.name} ↑ group`}
                      color="warning"
                      variant="dashed"
                      className={styles.inherited}
                    />
                  ))}
                  {selected.directRoles.length === 0 &&
                    inheritedRoles.length === 0 && (
                      <span className={styles.inheritedNote}>(no roles)</span>
                    )}
                  <MultiSelect
                    options={availableRoles}
                    value={[]}
                    onChange={(roleIds) => {
                      for (const roleId of roleIds) {
                        assignRole.mutate(
                          { userId: selected.userId, roleId },
                          {
                            onSuccess: () =>
                              toast({
                                title: 'Role assigned',
                                variant: 'success',
                              }),
                            onError: () =>
                              toast({
                                title: 'Failed to assign role',
                                variant: 'error',
                                duration: 86_400_000,
                              }),
                          },
                        );
                      }
                    }}
                    placeholder="+ Add"
                  />
                </div>
                {inheritedRoles.length > 0 && (
                  <span className={styles.inheritedNote}>
                    Roles with ↑ are inherited through group membership
                  </span>
                )}
              </div>
            </>
          ) : null
        }
        emptyMessage="Select a user to view details"
      />

      <ConfirmDialog
        open={deleteTarget !== null}
        onClose={() => setDeleteTarget(null)}
        onConfirm={handleDelete}
        message={`Delete user "${deleteTarget?.displayName}"? This cannot be undone.`}
        confirmText={deleteTarget?.displayName ?? ''}
        loading={deleteUser.isPending}
      />
      <AlertDialog
        open={removeGroupTarget !== null}
        onClose={() => setRemoveGroupTarget(null)}
        onConfirm={() => {
          if (removeGroupTarget && selected) {
            removeFromGroup.mutate(
              { userId: selected.userId, groupId: removeGroupTarget },
              {
                onSuccess: () =>
                  toast({ title: 'Group removed', variant: 'success' }),
                onError: () =>
                  toast({
                    title: 'Failed to remove group',
                    variant: 'error',
                    duration: 86_400_000,
                  }),
              },
            );
          }
          setRemoveGroupTarget(null);
        }}
        title="Remove group membership"
        description="Removing this group may also revoke inherited roles. Continue?"
        confirmLabel="Remove"
        variant="warning"
      />
      <AlertDialog
        open={removeRoleTarget !== null}
        onClose={() => setRemoveRoleTarget(null)}
        onConfirm={() => {
          if (removeRoleTarget && selected) {
            removeRole.mutate(
              { userId: selected.userId, roleId: removeRoleTarget.id },
              {
                onSuccess: () => {
                  toast({ title: 'Role removed', description: removeRoleTarget.name, variant: 'success' });
                  setRemoveRoleTarget(null);
                },
                onError: () => {
                  toast({ title: 'Failed to remove role', variant: 'error', duration: 86_400_000 });
                  setRemoveRoleTarget(null);
                },
              },
            );
          }
        }}
        title="Remove role"
        description={`Remove the "${removeRoleTarget?.name}" role from this user?`}
        confirmLabel="Remove"
        variant="warning"
      />
    </>
  );
}
