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 { useRoles, useCreateRole, useUpdateRole, useDeleteRole, usePermissions } from '@/api/hooks';
import type { PermissionItem, FieldDefinition } 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 { 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';

interface Role {
  id: string;
  name: string;
  permissions: Record<string, any>;
  denied_permissions?: string[];
  field_permissions?: Record<string, any>;
}

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];
}

export function SettingsRolesPage() {
  const { t } = useTranslation();
  const toast = useToast();
  const { data, isLoading, isError, error, refetch } = useRoles();
  const { data: permissionsData, isLoading: permissionsLoading } = usePermissions();
  const createRoleMutation = useCreateRole();
  const updateRoleMutation = useUpdateRole();
  const deleteRoleMutation = useDeleteRole();

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

  const { register: registerRole, handleSubmit: handleSubmitRole, reset: resetRole, formState: { errors: roleErrors } } = useForm<RoleCreateFormData>({
    resolver: zodResolver(roleCreateSchema),
    defaultValues: { name: '' },
  });

  const [createOpen, setCreateOpen] = useState(false);
  const [newRolePermissions, setNewRolePermissions] = useState<Record<string, any>>({});
  const [newRoleDenied, setNewRoleDenied] = useState<string[]>([]);
  const [editingRole, setEditingRole] = useState<Role | null>(null);
  const [confirmDelete, setConfirmDelete] = useState<Role | null>(null);
  const [editTab, setEditTab] = useState<'permissions' | 'denied' | 'fields'>('permissions');

  const roles: Role[] = 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 fieldDefinitions: FieldDefinition[] = useMemo(() => {
    return permissionsData?.field_definitions ?? [];
  }, [permissionsData]);

  const groupedFieldDefinitions = useMemo(() => {
    const groups: Record<string, FieldDefinition[]> = {};
    for (const fd of fieldDefinitions) {
      if (!groups[fd.module]) {
        groups[fd.module] = [];
      }
      groups[fd.module].push(fd);
    }
    return groups;
  }, [fieldDefinitions]);

  const handleCreateRole = async (data: RoleCreateFormData) => {
    try {
      await createRoleMutation.mutateAsync({
        name: data.name.trim(),
        permissions: newRolePermissions,
        denied_permissions: newRoleDenied,
        field_permissions: {},
      } as any);
      toast.success(t('settings.roleCreated'));
      resetRole({ name: '' });
      setNewRolePermissions({});
      setNewRoleDenied([]);
      setCreateOpen(false);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

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

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

  const handleFieldPermChange = (module: string, field: string, value: 'hidden' | 'readonly' | 'read' | 'default') => {
    if (!editingRole) return;
    const fieldPerms = { ...(editingRole.field_permissions || {}) };
    if (!fieldPerms[module]) {
      fieldPerms[module] = {};
    }
    if (value === 'default') {
      delete fieldPerms[module][field];
      if (Object.keys(fieldPerms[module]).length === 0) {
        delete fieldPerms[module];
      }
    } else {
      fieldPerms[module][field] = value;
    }
    setEditingRole({ ...editingRole, field_permissions: fieldPerms });
  };

  const handleSaveRole = async () => {
    if (!editingRole) return;
    try {
      await updateRoleMutation.mutateAsync({
        id: editingRole.id,
        data: {
          name: editingRole.name,
          permissions: editingRole.permissions,
          denied_permissions: editingRole.denied_permissions || [],
          field_permissions: editingRole.field_permissions || {},
        } as any,
      });
      toast.success(t('settings.roleUpdated'));
      setEditingRole(null);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  const handleDeleteRole = async () => {
    if (!confirmDelete) return;
    try {
      await deleteRoleMutation.mutateAsync(confirmDelete.id);
      toast.success(t('settings.roleDeleted'));
      setConfirmDelete(null);
    } catch (err: any) {
      toast.error(err.message || t('common.error'));
    }
  };

  if (isLoading || permissionsLoading) {
    return (
      <div className="p-6 max-w-4xl mx-auto" data-testid="settings-roles-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-roles-page">
        <h1 className="text-2xl font-bold text-secondary-900 mb-6">{t('settings.roles')}</h1>
        <EmptyState
          title={t('common.error')}
          description={error?.message || t('common.error')}
          action={<Button onClick={() => refetch()}>{t('common.reset')}</Button>}
        />
      </div>
    );
  }

  return (
    <div className="p-6 max-w-4xl mx-auto" data-testid="settings-roles-page">
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-2xl font-bold text-secondary-900">{t('settings.roles')}</h1>
        <Button onClick={() => { resetRole({ name: '' }); setCreateOpen(true); }} data-testid="create-role-btn">
          {t('settings.createRole')}
        </Button>
      </div>

      {roles.length === 0 ? (
        <EmptyState
          title={t('settings.noRoles')}
          action={<Button onClick={() => setCreateOpen(true)}>{t('settings.createRole')}</Button>}
        />
      ) : (
        <div className="space-y-4">
          {roles.map((role) => {
            const grantedKeys = getGrantedPermissionKeys(role.permissions);
            return (
              <Card key={role.id}>
                <div className="flex items-center justify-between mb-3">
                  <h3 className="text-lg font-semibold text-secondary-900">{role.name}</h3>
                  <div className="flex items-center gap-2">
                    <Button
                      variant="secondary"
                      size="sm"
                      onClick={() => setEditingRole(role)}
                      data-testid={`edit-role-${role.id}`}
                    >
                      {t('common.edit')}
                    </Button>
                    <Button
                      variant="danger"
                      size="sm"
                      onClick={() => setConfirmDelete(role)}
                      data-testid={`delete-role-${role.id}`}
                    >
                      {t('common.delete')}
                    </Button>
                  </div>
                </div>
                <div className="flex flex-wrap gap-2">
                  {grantedKeys.length === 0 ? (
                    <span className="text-sm text-secondary-500">—</span>
                  ) : (
                    grantedKeys.map((perm) => {
                      const label = permissionLabelMap.get(perm) || perm;
                      return <Badge key={perm} variant="primary">{label}</Badge>;
                    })
                  )}
                </div>
              </Card>
            );
          })}
        </div>
      )}

      <Modal open={createOpen} onClose={() => setCreateOpen(false)} title={t('settings.createRole')}>
        <form onSubmit={handleSubmitRole(handleCreateRole)} className="space-y-4" data-testid="create-role-form">
          <Input
            label={t('settings.roleName')}
            {...registerRole('name')}
            error={roleErrors.name?.message === 'required' ? t('validation.required') : undefined}
            placeholder={t('settings.roleName')}
            data-testid="new-role-name"
          />
          <div>
            <label className="block text-sm font-medium text-secondary-700 mb-2">{t('settings.permissions')}</label>
            <div className="space-y-2">
              {allPermissions.length === 0 && (
                <p className="text-sm text-secondary-500">{t('settings.noPermissions')}</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') : t('settings.pluginPermissions')}
                  </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(newRolePermissions, 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')}</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={newRoleDenied.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={createRoleMutation.isPending}
              data-testid="save-role-btn"
            >
              {t('common.save')}
            </Button>
          </div>
        </form>
      </Modal>

      <Modal open={!!editingRole} onClose={() => setEditingRole(null)} title={t('settings.roles') + ' — ' + (editingRole?.name || '')} size="xl">
        {editingRole && (
          <div className="space-y-4" data-testid="edit-role-form">
            <Input
              label={t('settings.roleName')}
              value={editingRole.name}
              onChange={(e) => setEditingRole({ ...editingRole, name: e.target.value })}
            />
            {/* Tab Navigation */}
            <div className="flex gap-2 border-b border-secondary-200 pb-2">
              <button
                className={`px-4 py-2 text-sm font-medium rounded-md transition-colors ${editTab === 'permissions' ? 'bg-primary-100 text-primary-700' : 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'}`}
                onClick={() => setEditTab('permissions')}
                data-testid="role-tab-permissions"
              >
                {t('settings.permissions')}
              </button>
              <button
                className={`px-4 py-2 text-sm font-medium rounded-md transition-colors ${editTab === 'denied' ? 'bg-primary-100 text-primary-700' : 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'}`}
                onClick={() => setEditTab('denied')}
                data-testid="role-tab-denied"
              >
                {t('settings.deniedPermissions', 'Verweigert')}
              </button>
              <button
                className={`px-4 py-2 text-sm font-medium rounded-md transition-colors ${editTab === 'fields' ? 'bg-primary-100 text-primary-700' : 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'}`}
                onClick={() => setEditTab('fields')}
                data-testid="role-tab-fields"
              >
                {t('settings.fieldPermissions', 'Feld-Berechtigungen')}
              </button>
            </div>

            {/* Permissions Tab */}
            {editTab === 'permissions' && (
              <div>
                <label className="block text-sm font-medium text-secondary-700 mb-2">{t('settings.permissions')}</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')}</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') : t('settings.pluginPermissions')}
                      </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(editingRole.permissions, perm.key)}
                            onChange={() => handleTogglePermission(perm.key, 'edit')}
                            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 */}
            {editTab === '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.')}
                </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')}</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={(editingRole.denied_permissions || []).includes(perm.key)}
                        onChange={() => handleToggleDenied(perm.key, 'edit')}
                        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>
            )}

            {/* Field Permissions Tab */}
            {editTab === 'fields' && (
              <div>
                <label className="block text-sm font-medium text-secondary-700 mb-2">
                  {t('settings.fieldPermissions', 'Feld-Berechtigungen')}
                </label>
                {fieldDefinitions.length === 0 ? (
                  <p className="text-sm text-secondary-500">
                    {t('settings.noFieldDefinitions', 'Keine Feld-Definitionen verfügbar')}
                  </p>
                ) : (
                  <div className="space-y-3 max-h-64 overflow-y-auto border border-secondary-200 rounded-md p-3">
                    {Object.entries(groupedFieldDefinitions).map(([moduleName, fields]) => (
                      <div key={moduleName} className="mb-3">
                        <p className="text-xs font-semibold text-secondary-500 uppercase mb-1">{moduleName}</p>
                        {fields.map((fd) => {
                          const currentVal = (editingRole.field_permissions || {})[moduleName]?.[fd.field] || 'default';
                          return (
                            <div key={`${moduleName}-${fd.field}`} className="flex items-center justify-between p-2 rounded-md hover:bg-secondary-50">
                              <div className="flex-1">
                                <span className="text-sm text-secondary-900">{fd.label}</span>
                                <span className="text-xs text-secondary-400 ml-2">({fd.sensitivity})</span>
                              </div>
                              <select
                                value={currentVal}
                                onChange={(e) => handleFieldPermChange(moduleName, fd.field, e.target.value as any)}
                                className="text-sm rounded-md border border-secondary-300 px-2 py-1 focus:ring-primary-500 focus:border-primary-500"
                                data-testid={`field-perm-${moduleName}-${fd.field}`}
                              >
                                <option value="default">{t('settings.fieldDefault', 'Standard')}</option>
                                <option value="read">{t('settings.fieldRead', 'Lesen')}</option>
                                <option value="readonly">{t('settings.fieldReadonly', 'Nur-Lesen')}</option>
                                <option value="hidden">{t('settings.fieldHidden', 'Versteckt')}</option>
                              </select>
                            </div>
                          );
                        })}
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}

            <div className="flex justify-end gap-3">
              <Button variant="secondary" onClick={() => setEditingRole(null)}>{t('common.cancel')}</Button>
              <Button
                onClick={handleSaveRole}
                isLoading={updateRoleMutation.isPending}
                data-testid="update-role-btn"
              >
                {t('common.save')}
              </Button>
            </div>
          </div>
        )}
      </Modal>

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