import React, { useCallback, useEffect, useState } from 'react';
import { Box, Text, useInput } from 'ink';
import type { RoleDTO, UserDTO } from '@effigenix/api-client';
import { useNavigation } from '../../state/navigation-context.js';
import { client } from '../../utils/api-client.js';
import { LoadingSpinner } from '../shared/LoadingSpinner.js';
import { ErrorDisplay } from '../shared/ErrorDisplay.js';
import { SuccessDisplay } from '../shared/SuccessDisplay.js';
import { ConfirmDialog } from '../shared/ConfirmDialog.js';
import { RoleSelectList } from '../roles/RoleSelectList.js';

type MenuAction = 'toggle-lock' | 'assign-role' | 'remove-role' | 'change-password' | 'back';
type Mode = 'menu' | 'confirm-lock' | 'assign-role' | 'remove-role';

interface MenuItem {
  id: MenuAction;
  label: (user: UserDTO) => string;
}

const MENU_ITEMS: MenuItem[] = [
  { id: 'toggle-lock', label: (u) => (u.status === 'ACTIVE' ? '[Sperren]' : '[Entsperren]') },
  { id: 'assign-role', label: () => '[Rolle zuweisen]' },
  { id: 'remove-role', label: () => '[Rolle entfernen]' },
  { id: 'change-password', label: () => '[Passwort ändern]' },
  { id: 'back', label: () => '[Zurück]' },
];

function errorMessage(err: unknown): string {
  return err instanceof Error ? err.message : 'Unbekannter Fehler';
}

export function UserDetailScreen() {
  const { params, navigate, back } = useNavigation();
  const userId = params['userId'] ?? '';

  const [user, setUser] = useState<UserDTO | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [selectedAction, setSelectedAction] = useState(0);
  const [mode, setMode] = useState<Mode>('menu');
  const [availableRoles, setAvailableRoles] = useState<RoleDTO[]>([]);
  const [actionLoading, setActionLoading] = useState(false);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);

  const loadUser = async () => {
    setLoading(true);
    setError(null);
    try {
      const u = await client.users.getById(userId);
      setUser(u);
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (userId) {
      void loadUser();
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId]);

  useInput((_input, key) => {
    if (loading || actionLoading || mode !== 'menu') return;

    if (key.upArrow) {
      setSelectedAction((i) => Math.max(0, i - 1));
    }
    if (key.downArrow) {
      setSelectedAction((i) => Math.min(MENU_ITEMS.length - 1, i + 1));
    }
    if (key.return) {
      void handleAction();
    }
    if (key.backspace || key.escape) {
      back();
    }
  });

  const handleAction = async () => {
    if (!user) return;
    const item = MENU_ITEMS[selectedAction];
    if (!item) return;

    switch (item.id) {
      case 'toggle-lock': {
        setMode('confirm-lock');
        break;
      }
      case 'assign-role': {
        setActionLoading(true);
        try {
          const allRoles = await client.roles.list();
          const userRoleIds = new Set(user.roles.map((r) => r.id));
          setAvailableRoles(allRoles.filter((r) => !userRoleIds.has(r.id)));
        } catch (err) {
          setError(errorMessage(err));
        } finally {
          setActionLoading(false);
        }
        setMode('assign-role');
        break;
      }
      case 'remove-role': {
        setAvailableRoles(user.roles);
        setMode('remove-role');
        break;
      }
      case 'change-password': {
        navigate('change-password', { userId: user.id });
        break;
      }
      case 'back': {
        back();
        break;
      }
    }
  };

  const handleToggleLock = useCallback(async () => {
    if (!user) return;
    setMode('menu');
    setActionLoading(true);
    setError(null);
    try {
      const updated = user.status === 'ACTIVE'
        ? await client.users.lock(user.id)
        : await client.users.unlock(user.id);
      setUser(updated);
      setSuccessMessage(user.status === 'ACTIVE' ? 'Benutzer gesperrt.' : 'Benutzer entsperrt.');
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setActionLoading(false);
    }
  }, [user]);

  const handleRoleSelect = useCallback(async (role: RoleDTO) => {
    if (!user) return;
    const currentMode = mode;
    setMode('menu');
    setActionLoading(true);
    setError(null);
    try {
      if (currentMode === 'assign-role') {
        const updated = await client.users.assignRole(user.id, { roleName: role.name });
        setUser(updated);
        setSuccessMessage(`Rolle "${role.name}" zugewiesen.`);
      } else {
        await client.users.removeRole(user.id, role.name);
        const updated = await client.users.getById(user.id);
        setUser(updated);
        setSuccessMessage(`Rolle "${role.name}" entfernt.`);
      }
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setActionLoading(false);
    }
  }, [user, mode]);

  if (loading) {
    return <LoadingSpinner label="Lade Benutzerdetails..." />;
  }

  if (error && !user) {
    return <ErrorDisplay message={error} onDismiss={() => setError(null)} />;
  }

  if (!user) {
    return <Text color="red">Benutzer nicht gefunden.</Text>;
  }

  const roleNames = user.roles.map((r) => r.name).join(', ') || '–';
  const statusColor = user.status === 'ACTIVE' ? 'green' : 'red';

  return (
    <Box flexDirection="column" gap={1}>
      <Text color="cyan" bold>
        Benutzerdetails
      </Text>

      {error && <ErrorDisplay message={error} onDismiss={() => setError(null)} />}
      {successMessage && (
        <SuccessDisplay message={successMessage} onDismiss={() => setSuccessMessage(null)} />
      )}

      {/* User Info */}
      <Box flexDirection="column" borderStyle="round" borderColor="gray" paddingX={2} paddingY={1}>
        <Box gap={2}>
          <Text color="gray">ID:</Text>
          <Text>{user.id}</Text>
        </Box>
        <Box gap={2}>
          <Text color="gray">Benutzername:</Text>
          <Text bold>{user.username}</Text>
        </Box>
        <Box gap={2}>
          <Text color="gray">E-Mail:</Text>
          <Text>{user.email}</Text>
        </Box>
        <Box gap={2}>
          <Text color="gray">Status:</Text>
          <Text color={statusColor} bold>
            {user.status}
          </Text>
        </Box>
        <Box gap={2}>
          <Text color="gray">Rollen:</Text>
          <Text>{roleNames}</Text>
        </Box>
        <Box gap={2}>
          <Text color="gray">Erstellt:</Text>
          <Text>{new Date(user.createdAt).toLocaleString('de-DE')}</Text>
        </Box>
        {user.lastLogin && (
          <Box gap={2}>
            <Text color="gray">Letzter Login:</Text>
            <Text>{new Date(user.lastLogin).toLocaleString('de-DE')}</Text>
          </Box>
        )}
      </Box>

      {/* Confirm Lock Dialog */}
      {mode === 'confirm-lock' && (
        <ConfirmDialog
          message={user.status === 'ACTIVE' ? 'Benutzer sperren?' : 'Benutzer entsperren?'}
          onConfirm={() => void handleToggleLock()}
          onCancel={() => setMode('menu')}
        />
      )}

      {/* Role Select */}
      {(mode === 'assign-role' || mode === 'remove-role') && (
        <RoleSelectList
          roles={availableRoles}
          label={mode === 'assign-role' ? 'Rolle zuweisen:' : 'Rolle entfernen:'}
          onSelect={(role) => void handleRoleSelect(role)}
          onCancel={() => setMode('menu')}
        />
      )}

      {/* Action Menu */}
      {mode === 'menu' && (
        <Box flexDirection="column">
          <Text color="gray" bold>
            Aktionen:
          </Text>
          {actionLoading && <LoadingSpinner label="Aktion wird ausgeführt..." />}
          {!actionLoading &&
            MENU_ITEMS.map((item, index) => (
              <Box key={item.id}>
                <Text color={index === selectedAction ? 'cyan' : 'white'}>
                  {index === selectedAction ? '▶ ' : '  '}
                  {item.label(user)}
                </Text>
              </Box>
            ))}
        </Box>
      )}

      <Box marginTop={1}>
        <Text color="gray" dimColor>
          ↑↓ navigieren · Enter ausführen · Backspace Zurück
        </Text>
      </Box>
    </Box>
  );
}
