import React, { useState, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import {
  useGroups,
  useCreateGroup,
  useUpdateGroup,
  useDeleteGroup,
  usePermissions,
  useGroupMembers,
  useAddGroupMember,
  useRemoveGroupMember,
  useUsers,
} from '@/api/hooks';
import type { PermissionItem, Group, GroupMember } from '@/api/hooks';
import { Input } from '@/components/ui/Input';
import { Button } from '@/components/ui/Button';
import { Card } from '@/components/ui/Card';
import { Badge } from '@/components/ui/Badge';
import { Select } from '@/components/ui/Select';
import { EmptyState } from '@/components/ui/EmptyState';
import { Skeleton } from '@/components/ui/Skeleton';
import { useToast } from '@/components/ui/Toast';
import { Modal } from '@/components/ui/Modal';
import { ConfirmDialog } from '@/components/ui/ConfirmDialog';

function isPermissionGranted(permissions: Record<string, any>, permKey: string): boolean {
  if (!permissions) return false;
  if (typeof permissions === 'boolean') return permissions;
  if (Array.isArray(permissions)) return permissions.includes(permKey);
  if (typeof permissions === 'object') {
    if (permKey in permissions) {
      const val = permissions[permKey];
      return val === true || val === 'true' || val === 1;
    }
    if ('all' in permissions && permissions.all === true) return true;
  }
  return false;
}

function togglePermission(
  permissions: Record<string, any>,
  permKey: string
): Record<string, any> {
  const current = isPermissionGranted(permissions, permKey);
  return { ...permissions, [permKey]: !current };
}

function getGrantedPermissionKeys(permissions: Record<string, any>): string[] {
  if (!permissions) return [];
  if (Array.isArray(permissions)) return permissions as string[];
  if (typeof permissions === 'object') {
    return Object.keys(permissions).filter(
      (k) => k !== 'all' && permissions[k] === true
    );
  }
  return [];
}

function toggleDeniedPermission(denied: string[], permKey: string): string[] {
  if (denied.includes(permKey)) {
    return denied.filter((k) => k !== permKey);
  }
  return [...denied, permKey];
}

interface EditingGroup extends Partial<Group> {
  id?: string;
  name: string;
  description: string;
  permissions: Record<string, any>;
  denied_permissions: string[];
  field_permissions: Record<string, any>;
}

export function SettingsGroupsPage() {
  const { t } = useTranslation();
  const toast = useToast();
  const { data, isLoading, isError, error, refetch } = useGroups();
  const { data: permissionsData, isLoading: permissionsLoading } = usePermissions();
  const createGroupMutation = useCreateGroup();
  const updateGroupMutation = useUpdateGroup();
  const deleteGroupMutation = useDeleteGroup();

  // ── Zod Schema for create form ──
  const groupCreateSchema = z.object({
    name: z.string().min(1, 'required'),
    description: z.string().optional().default(''),
  });
  type GroupCreateFormData = z.infer<typeof groupCreateSchema>;

  const { register: registerGroup, handleSubmit: handleSubmitGroup, reset: resetGroup, formState: { errors: groupErrors } } = useForm<GroupCreateFormData>({
    resolver: zodResolver(groupCreateSchema),
    defaultValues: { name: '', description: '' },
  });

  const [createOpen, setCreateOpen] = useState(false);
  const [newGroupPermissions, setNewGroupPermissions] = useState<Record<string, any>>({});
  const [newGroupDenied, setNewGroupDenied] = useState<string[]>([]);
  const [editingGroup, setEditingGroup] = useState<EditingGroup | null>(null);
  const [confirmDelete, setConfirmDelete] = useState<Group | null>(null);

  // Member management state
  const [memberSearchUserId, setMemberSearchUserId] = useState('');

  const groups: Group[] = data?.items ?? [];

  const allPermissions: PermissionItem[] = useMemo(() => {
    return permissionsData?.all ?? [];
  }, [permissionsData]);

  const permissionLabelMap = useMemo(() => {
    const map = new Map<string, string>();
    for (const perm of allPermissions) {
      map.set(perm.key, perm.label);
    }
    return map;
  }, [allPermissions]);

  const groupedPermissions = useMemo(() => {
    const groups: Record<string, PermissionItem[]> = {};
    for (const perm of allPermissions) {
      if (!groups[perm.category]) {
        groups[perm.category] = [];
      }
      groups[perm.category].push(perm);
    }
    return groups;
  }, [allPermissions]);

  const handleCreateGroup = async (data: GroupCreateFormData) => {
    try {
      await createGroupMutation.mutateAsync({
        name: data.name.trim(),
        description: data.description.trim() || null,
        permissions: newGroupPermissions,
        denied_permissions: newGroupDenied,
        field_permissions: {},
      });
      toast.success(t('settings.groupCreated', 'Gruppe erstellt'));
      resetGroup({ name: '', description: '' });
      setNewGroupPermissions({});
      setNewGroupDenied([]);
      setCreateOpen(false);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const handleTogglePermission = (permKey: string, target: 'new' | 'edit') => {
    if (target === 'new') {
      setNewGroupPermissions((prev) => togglePermission(prev, permKey));
    } else if (editingGroup) {
      setEditingGroup({
        ...editingGroup,
        permissions: togglePermission(editingGroup.permissions || {}, permKey),
      });
    }
  };

  const handleToggleDenied = (permKey: string, target: 'new' | 'edit') => {
    if (target === 'new') {
      setNewGroupDenied((prev) => toggleDeniedPermission(prev, permKey));
    } else if (editingGroup) {
      setEditingGroup({
        ...editingGroup,
        denied_permissions: toggleDeniedPermission(editingGroup.denied_permissions || [], permKey),
      });
    }
  };

  const handleSaveGroup = async () => {
    if (!editingGroup || !editingGroup.id) return;
    if (!editingGroup.name.trim()) {
      toast.error(t('validation.required', 'Pflichtfeld'));
      return;
    }
    try {
      await updateGroupMutation.mutateAsync({
        id: editingGroup.id,
        data: {
          name: editingGroup.name.trim(),
          description: editingGroup.description.trim() || null,
          permissions: editingGroup.permissions,
          denied_permissions: editingGroup.denied_permissions,
          field_permissions: editingGroup.field_permissions || {},
        },
      });
      toast.success(t('settings.groupUpdated', 'Gruppe aktualisiert'));
      setEditingGroup(null);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const handleDeleteGroup = async () => {
    if (!confirmDelete) return;
    try {
      await deleteGroupMutation.mutateAsync(confirmDelete.id);
      toast.success(t('settings.groupDeleted', 'Gruppe gelöscht'));
      setConfirmDelete(null);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const startEdit = (group: Group) => {
    setEditingGroup({
      id: group.id,
      name: group.name,
      description: group.description || '',
      permissions: group.permissions || {},
      denied_permissions: group.denied_permissions || [],
      field_permissions: group.field_permissions || {},
    });
  };

  if (isLoading || permissionsLoading) {
    return (
      <div className="p-6 max-w-4xl mx-auto" data-testid="settings-groups-page">
        <Skeleton className="h-8 w-48 mb-6" />
        <div className="space-y-3">
          <Skeleton className="h-16" />
          <Skeleton className="h-16" />
          <Skeleton className="h-16" />
        </div>
      </div>
    );
  }

  if (isError) {
    return (
      <div className="p-6 max-w-4xl mx-auto" data-testid="settings-groups-page">
        <h1 className="text-2xl font-bold text-secondary-900 mb-6">
          {t('settings.groups', 'Gruppen')}
        </h1>
        <EmptyState
          title={t('common.error')}
          description={error?.message || t('common.error')}
          action={<Button onClick={() => refetch()}>{t('common.reset', 'Erneut versuchen')}</Button>}
        />
      </div>
    );
  }

  return (
    <div className="p-6 max-w-4xl mx-auto" data-testid="settings-groups-page">
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-2xl font-bold text-secondary-900">
          {t('settings.groups', 'Gruppen')}
        </h1>
        <Button onClick={() => { resetGroup({ name: '', description: '' }); setCreateOpen(true); }} data-testid="create-group-btn">
          {t('settings.createGroup', 'Gruppe erstellen')}
        </Button>
      </div>

      {groups.length === 0 ? (
        <EmptyState
          title={t('settings.noGroups', 'Keine Gruppen vorhanden')}
          action={<Button onClick={() => setCreateOpen(true)}>{t('settings.createGroup', 'Gruppe erstellen')}</Button>}
        />
      ) : (
        <div className="space-y-4">
          {groups.map((group) => {
            const grantedKeys = getGrantedPermissionKeys(group.permissions);
            const deniedCount = (group.denied_permissions || []).length;
            return (
              <Card key={group.id}>
                <div className="flex items-center justify-between mb-3">
                  <div className="flex-1 min-w-0">
                    <h3 className="text-lg font-semibold text-secondary-900">{group.name}</h3>
                    {group.description && (
                      <p className="text-sm text-secondary-500 mt-1">{group.description}</p>
                    )}
                  </div>
                  <div className="flex items-center gap-2">
                    <Button
                      variant="secondary"
                      size="sm"
                      onClick={() => startEdit(group)}
                      data-testid={`edit-group-${group.id}`}
                    >
                      {t('common.edit')}
                    </Button>
                    <Button
                      variant="danger"
                      size="sm"
                      onClick={() => setConfirmDelete(group)}
                      data-testid={`delete-group-${group.id}`}
                    >
                      {t('common.delete')}
                    </Button>
                  </div>
                </div>
                <div className="flex flex-wrap gap-2 items-center">
                  {grantedKeys.length === 0 ? (
                    <span className="text-sm text-secondary-500">—</span>
                  ) : (
                    grantedKeys.slice(0, 10).map((perm) => {
                      const label = permissionLabelMap.get(perm) || perm;
                      return <Badge key={perm} variant="primary">{label}</Badge>;
                    })
                  )}
                  {grantedKeys.length > 10 && (
                    <Badge variant="default">+{grantedKeys.length - 10}</Badge>
                  )}
                  {deniedCount > 0 && (
                    <Badge variant="danger">
                      {deniedCount} {t('settings.denied', 'verweigert')}
                    </Badge>
                  )}
                </div>
              </Card>
            );
          })}
        </div>
      )}

      {/* Create Group Modal */}
      <Modal
        open={createOpen}
        onClose={() => setCreateOpen(false)}
        title={t('settings.createGroup', 'Gruppe erstellen')}
        size="lg"
      >
        <form onSubmit={handleSubmitGroup(handleCreateGroup)} className="space-y-4" data-testid="create-group-form">
          <Input
            label={t('settings.groupName', 'Gruppenname')}
            {...registerGroup('name')}
            error={groupErrors.name?.message === 'required' ? t('validation.required') : undefined}
            placeholder={t('settings.groupName', 'Gruppenname')}
            data-testid="new-group-name"
          />
          <Input
            label={t('settings.groupDescription', 'Beschreibung')}
            {...registerGroup('description')}
            placeholder={t('settings.groupDescription', 'Beschreibung')}
            data-testid="new-group-description"
          />
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-2">
              {t('settings.permissions', 'Berechtigungen')}
            </label>
            <div className="space-y-2 max-h-48 overflow-y-auto border border-secondary-200 rounded-md p-3">
              {allPermissions.length === 0 && (
                <p className="text-sm text-secondary-500">{t('settings.noPermissions', 'Keine Berechtigungen verfügbar')}</p>
              )}
              {Object.entries(groupedPermissions).map(([category, perms]) => (
                <div key={category} className="mb-3">
                  <p className="text-xs font-semibold text-secondary-500 uppercase mb-1">
                    {category === 'system' ? t('settings.systemPermissions', 'System') : t('settings.pluginPermissions', 'Plugins')}
                  </p>
                  {perms.map((perm) => (
                    <label key={perm.key} className="flex items-center gap-2 p-2 rounded-md hover:bg-secondary-50 cursor-pointer min-h-touch">
                      <input
                        type="checkbox"
                        checked={isPermissionGranted(newGroupPermissions, perm.key)}
                        onChange={() => handleTogglePermission(perm.key, 'new')}
                        className="w-4 h-4 rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                      />
                      <span className="text-sm text-secondary-900">{perm.label}</span>
                    </label>
                  ))}
                </div>
              ))}
            </div>
          </div>
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-2">
              {t('settings.deniedPermissions', 'Verweigerte Berechtigungen')}
            </label>
            <div className="space-y-2 max-h-32 overflow-y-auto border border-secondary-200 rounded-md p-3">
              {allPermissions.length === 0 && (
                <p className="text-sm text-secondary-500">{t('settings.noPermissions', 'Keine Berechtigungen verfügbar')}</p>
              )}
              {allPermissions.map((perm) => (
                <label key={`denied-${perm.key}`} className="flex items-center gap-2 p-2 rounded-md hover:bg-secondary-50 cursor-pointer min-h-touch">
                  <input
                    type="checkbox"
                    checked={newGroupDenied.includes(perm.key)}
                    onChange={() => handleToggleDenied(perm.key, 'new')}
                    className="w-4 h-4 rounded border-danger-300 text-danger-600 focus:ring-danger-500"
                  />
                  <span className="text-sm text-secondary-900">{perm.label}</span>
                </label>
              ))}
            </div>
          </div>
          <div className="flex justify-end gap-3">
            <Button variant="secondary" onClick={() => setCreateOpen(false)}>{t('common.cancel')}</Button>
            <Button
              type="submit"
              isLoading={createGroupMutation.isPending}
              data-testid="save-group-btn"
            >
              {t('common.save')}
            </Button>
          </div>
        </form>
      </Modal>

      {/* Edit Group Modal */}
      <Modal
        open={!!editingGroup}
        onClose={() => setEditingGroup(null)}
        title={t('settings.groups', 'Gruppen') + ' — ' + (editingGroup?.name || '')}
        size="xl"
      >
        {editingGroup && (
          <EditGroupContent
            group={editingGroup}
            onChange={setEditingGroup}
            onTogglePermission={(key) => handleTogglePermission(key, 'edit')}
            onToggleDenied={(key) => handleToggleDenied(key, 'edit')}
            allPermissions={allPermissions}
            groupedPermissions={groupedPermissions}
            permissionLabelMap={permissionLabelMap}
            onSave={handleSaveGroup}
            onCancel={() => setEditingGroup(null)}
            isSaving={updateGroupMutation.isPending}
            memberSearchUserId={memberSearchUserId}
            setMemberSearchUserId={setMemberSearchUserId}
          />
        )}
      </Modal>

      <ConfirmDialog
        open={!!confirmDelete}
        title={t('common.delete')}
        message={`${t('common.delete')}: ${confirmDelete?.name}?`}
        variant="danger"
        onConfirm={handleDeleteGroup}
        onCancel={() => setConfirmDelete(null)}
      />
    </div>
  );
}

// ─── Edit Group Content with Tabs ─────────────────────────────────────────────

interface EditGroupContentProps {
  group: EditingGroup;
  onChange: (group: EditingGroup) => void;
  onTogglePermission: (key: string) => void;
  onToggleDenied: (key: string) => void;
  allPermissions: PermissionItem[];
  groupedPermissions: Record<string, PermissionItem[]>;
  permissionLabelMap: Map<string, string>;
  onSave: () => void;
  onCancel: () => void;
  isSaving: boolean;
  memberSearchUserId: string;
  setMemberSearchUserId: (val: string) => void;
}

function EditGroupContent({
  group,
  onChange,
  onTogglePermission,
  onToggleDenied,
  allPermissions,
  groupedPermissions,
  permissionLabelMap,
  onSave,
  onCancel,
  isSaving,
  memberSearchUserId,
  setMemberSearchUserId,
}: EditGroupContentProps) {
  const { t } = useTranslation();
  const toast = useToast();
  const [activeTab, setActiveTab] = useState<'details' | 'permissions' | 'denied' | 'members'>('details');

  const groupId = group.id || null;
  const { data: membersData, isLoading: membersLoading } = useGroupMembers(groupId);
  const { data: usersData } = useUsers(1, 100);
  const addMemberMutation = useAddGroupMember();
  const removeMemberMutation = useRemoveGroupMember();

  const members: GroupMember[] = membersData?.items ?? [];
  const allUsers = usersData?.items ?? [];

  // Users not yet in this group
  const availableUsers = useMemo(() => {
    const memberIds = new Set(members.map((m) => m.user_id));
    return allUsers.filter((u: any) => !memberIds.has(u.id));
  }, [allUsers, members]);

  const userSelectOptions = useMemo(() => {
    return availableUsers.map((u: any) => ({
      value: u.id,
      label: `${u.name || u.email} (${u.email})`,
    }));
  }, [availableUsers]);

  const handleAddMember = async () => {
    if (!groupId || !memberSearchUserId) return;
    try {
      await addMemberMutation.mutateAsync({ groupId, userId: memberSearchUserId });
      toast.success(t('settings.memberAdded', 'Mitglied hinzugefügt'));
      setMemberSearchUserId('');
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const handleRemoveMember = async (userId: string) => {
    if (!groupId) return;
    try {
      await removeMemberMutation.mutateAsync({ groupId, userId });
      toast.success(t('settings.memberRemoved', 'Mitglied entfernt'));
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const tabBtnClass = (tab: string) =>
    `px-4 py-2 text-sm font-medium rounded-md transition-colors ${
      activeTab === tab
        ? 'bg-primary-100 text-primary-700'
        : 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'
    }`;

  return (
    <div className="space-y-4" data-testid="edit-group-form">
      {/* Tab Navigation */}
      <div className="flex gap-2 border-b border-secondary-200 pb-2">
        <button className={tabBtnClass('details')} onClick={() => setActiveTab('details')} data-testid="tab-details">
          {t('settings.groupDetails', 'Details')}
        </button>
        <button className={tabBtnClass('permissions')} onClick={() => setActiveTab('permissions')} data-testid="tab-permissions">
          {t('settings.permissions', 'Berechtigungen')}
        </button>
        <button className={tabBtnClass('denied')} onClick={() => setActiveTab('denied')} data-testid="tab-denied">
          {t('settings.deniedPermissions', 'Verweigert')}
        </button>
        <button className={tabBtnClass('members')} onClick={() => setActiveTab('members')} data-testid="tab-members">
          {t('settings.members', 'Mitglieder')}
        </button>
      </div>

      {/* Details Tab */}
      {activeTab === 'details' && (
        <div className="space-y-4">
          <Input
            label={t('settings.groupName', 'Gruppenname')}
            value={group.name}
            onChange={(e) => onChange({ ...group, name: e.target.value })}
            data-testid="edit-group-name"
          />
          <Input
            label={t('settings.groupDescription', 'Beschreibung')}
            value={group.description}
            onChange={(e) => onChange({ ...group, description: e.target.value })}
            data-testid="edit-group-description"
          />
        </div>
      )}

      {/* Permissions Tab */}
      {activeTab === 'permissions' && (
        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-2">
            {t('settings.permissions', 'Berechtigungen')}
          </label>
          <div className="space-y-2 max-h-64 overflow-y-auto border border-secondary-200 rounded-md p-3">
            {allPermissions.length === 0 && (
              <p className="text-sm text-secondary-500">{t('settings.noPermissions', 'Keine Berechtigungen verfügbar')}</p>
            )}
            {Object.entries(groupedPermissions).map(([category, perms]) => (
              <div key={category} className="mb-3">
                <p className="text-xs font-semibold text-secondary-500 uppercase mb-1">
                  {category === 'system' ? t('settings.systemPermissions', 'System') : t('settings.pluginPermissions', 'Plugins')}
                </p>
                {perms.map((perm) => (
                  <label key={perm.key} className="flex items-center gap-2 p-2 rounded-md hover:bg-secondary-50 cursor-pointer min-h-touch">
                    <input
                      type="checkbox"
                      checked={isPermissionGranted(group.permissions || {}, perm.key)}
                      onChange={() => onTogglePermission(perm.key)}
                      className="w-4 h-4 rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
                    />
                    <span className="text-sm text-secondary-900">{perm.label}</span>
                  </label>
                ))}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Denied Permissions Tab */}
      {activeTab === 'denied' && (
        <div>
          <label className="block text-sm font-medium text-secondary-700 mb-2">
            {t('settings.deniedPermissions', 'Verweigerte Berechtigungen')}
          </label>
          <p className="text-xs text-secondary-500 mb-2">
            {t('settings.deniedPermissionsHint', 'Diese Berechtigungen werden explizit verweigert, auch wenn sie über Rollen gewährt wurden.')}
          </p>
          <div className="space-y-2 max-h-64 overflow-y-auto border border-secondary-200 rounded-md p-3">
            {allPermissions.length === 0 && (
              <p className="text-sm text-secondary-500">{t('settings.noPermissions', 'Keine Berechtigungen verfügbar')}</p>
            )}
            {allPermissions.map((perm) => (
              <label key={`denied-edit-${perm.key}`} className="flex items-center gap-2 p-2 rounded-md hover:bg-secondary-50 cursor-pointer min-h-touch">
                <input
                  type="checkbox"
                  checked={(group.denied_permissions || []).includes(perm.key)}
                  onChange={() => onToggleDenied(perm.key)}
                  className="w-4 h-4 rounded border-danger-300 text-danger-600 focus:ring-danger-500"
                />
                <span className="text-sm text-secondary-900">{perm.label}</span>
              </label>
            ))}
          </div>
        </div>
      )}

      {/* Members Tab */}
      {activeTab === 'members' && (
        <div className="space-y-4">
          <div className="flex gap-2 items-end">
            <div className="flex-1">
              <Select
                label={t('settings.addMember', 'Mitglied hinzufügen')}
                options={userSelectOptions}
                placeholder={t('settings.selectUser', 'Benutzer auswählen')}
                value={memberSearchUserId}
                onChange={(e) => setMemberSearchUserId(e.target.value)}
                data-testid="member-user-select"
              />
            </div>
            <Button
              onClick={handleAddMember}
              isLoading={addMemberMutation.isPending}
              disabled={!memberSearchUserId}
              data-testid="add-member-btn"
            >
              {t('common.add', 'Hinzufügen')}
            </Button>
          </div>

          <div className="border border-secondary-200 rounded-md">
            {membersLoading ? (
              <div className="p-4">
                <Skeleton className="h-12" />
              </div>
            ) : members.length === 0 ? (
              <div className="p-4 text-sm text-secondary-500">
                {t('settings.noMembers', 'Keine Mitglieder')}
              </div>
            ) : (
              <div className="divide-y divide-secondary-200" data-testid="group-members-list">
                {members.map((member) => (
                  <div key={member.user_id} className="flex items-center justify-between p-3">
                    <div className="flex-1 min-w-0">
                      <p className="font-medium text-secondary-900 truncate">{member.name}</p>
                      <p className="text-sm text-secondary-500 truncate">{member.email}</p>
                    </div>
                    <Badge variant={member.is_active === false ? 'danger' : 'success'} className="mr-2">
                      {member.is_active === false ? t('common.inactive') : t('common.active')}
                    </Badge>
                    <Button
                      variant="danger"
                      size="sm"
                      onClick={() => handleRemoveMember(member.user_id)}
                      data-testid={`remove-member-${member.user_id}`}
                    >
                      {t('common.remove', 'Entfernen')}
                    </Button>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Save / Cancel */}
      <div className="flex justify-end gap-3 pt-4 border-t border-secondary-200">
        <Button variant="secondary" onClick={onCancel}>{t('common.cancel')}</Button>
        <Button
          onClick={onSave}
          isLoading={isSaving}
          data-testid="update-group-btn"
        >
          {t('common.save')}
        </Button>
      </div>
    </div>
  );
}
