/**
 * AdminFeatureInstanceUsersPage
 * 
 * Admin page for managing user access to feature instances.
 * Allows adding, removing, and updating user roles within feature instances.
 */

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { useFeatureAccess, type FeatureAccessUser, type FeatureInstanceRole, type PaginationParams, type PaginationMetadata } from '../../hooks/useFeatureAccess';
import { useUserMandates } from '../../hooks/useUserMandates';
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm, type AttributeDefinition } from '../../components/FormGenerator/FormGeneratorForm';
import { FaPlus, FaSync, FaUsers, FaBuilding, FaCube } from 'react-icons/fa';
import { useToast } from '../../contexts/ToastContext';
import api from '../../api';
import styles from './Admin.module.css';

export const AdminFeatureInstanceUsersPage: React.FC = () => {
  const {
    features,
    instances,
    loading,
    error,
    fetchFeatures,
    fetchInstanceUsers,
    addUserToInstance,
    removeUserFromInstance,
    updateInstanceUserRoles,
    fetchInstanceRoles,
  } = useFeatureAccess();

  const { fetchMandates } = useUserMandates();
  const { showSuccess, showError } = useToast();

  // Combined instance option type
  interface CombinedInstanceOption {
    mandateId: string;
    instanceId: string;
    mandateName: string;
    instanceLabel: string;
    featureCode: string;
    combinedKey: string; // mandateId:instanceId for unique identification
  }

  // State
  const [combinedOptions, setCombinedOptions] = useState<CombinedInstanceOption[]>([]);
  const [selectedCombinedKey, setSelectedCombinedKey] = useState<string>('');
  const [instanceUsers, setInstanceUsers] = useState<FeatureAccessUser[]>([]);
  const [instanceRoles, setInstanceRoles] = useState<FeatureInstanceRole[]>([]);
  const [allUsers, setAllUsers] = useState<Array<{ id: string; username: string; email?: string; fullName?: string }>>([]);
  const [showAddModal, setShowAddModal] = useState(false);
  const [editingUser, setEditingUser] = useState<FeatureAccessUser | null>(null);
  const [, setIsSubmitting] = useState(false);
  const [usersLoading, setUsersLoading] = useState(false);
  const [usersPagination, setUsersPagination] = useState<PaginationMetadata | null>(null);

  // Extract mandateId and instanceId from combined key
  const selectedMandateId = useMemo(() => {
    if (!selectedCombinedKey) return '';
    return selectedCombinedKey.split(':')[0] || '';
  }, [selectedCombinedKey]);

  const selectedInstanceId = useMemo(() => {
    if (!selectedCombinedKey) return '';
    return selectedCombinedKey.split(':')[1] || '';
  }, [selectedCombinedKey]);

  // Load mandates and features on mount, then build combined options
  useEffect(() => {
    fetchFeatures();
    const loadCombinedOptions = async () => {
      const loadedMandates = await fetchMandates();
      
      // Load instances for all mandates in parallel
      const allOptions: CombinedInstanceOption[] = [];
      
      for (const mandate of loadedMandates) {
        try {
          const response = await api.get('/api/features/instances', {
            headers: { 'X-Mandate-Id': mandate.id }
          });
          const instanceList = response.data?.items || response.data || [];
          
          if (Array.isArray(instanceList)) {
            for (const inst of instanceList) {
              allOptions.push({
                mandateId: mandate.id,
                instanceId: inst.id,
                mandateName: typeof mandate.name === 'string' ? mandate.name : (mandate.name?.de || mandate.name?.en || Object.values(mandate.name || {})[0] || mandate.id),
                instanceLabel: inst.label || inst.id,
                featureCode: inst.featureCode,
                combinedKey: `${mandate.id}:${inst.id}`,
              });
            }
          }
        } catch (err) {
          console.error(`Error loading instances for mandate ${mandate.id}:`, err);
        }
      }
      
      // Sort by mandate name, then by instance label
      allOptions.sort((a, b) => {
        const mandateCompare = a.mandateName.localeCompare(b.mandateName);
        if (mandateCompare !== 0) return mandateCompare;
        return a.instanceLabel.localeCompare(b.instanceLabel);
      });
      
      setCombinedOptions(allOptions);
    };
    
    loadCombinedOptions();
  }, [fetchFeatures, fetchMandates]);

  // Load users and roles when instance changes
  useEffect(() => {
    if (selectedMandateId && selectedInstanceId) {
      setUsersLoading(true);
      Promise.all([
        fetchInstanceUsers(selectedMandateId, selectedInstanceId),
        fetchInstanceRoles(selectedMandateId, selectedInstanceId),
      ]).then(([users, roles]) => {
        setInstanceUsers(users);
        setInstanceRoles(roles);
      }).finally(() => {
        setUsersLoading(false);
      });
    }
  }, [selectedMandateId, selectedInstanceId, fetchInstanceUsers, fetchInstanceRoles]);

  // Load mandate members for the add modal (only users who are members of the selected mandate)
  useEffect(() => {
    if (!selectedMandateId) {
      setAllUsers([]);
      return;
    }
    api.get(`/api/mandates/${selectedMandateId}/users`).then(response => {
      const data = response.data?.items || response.data || [];
      // Map MandateUserInfo to the expected format
      const mappedUsers = Array.isArray(data) ? data.map((u: any) => ({
        id: u.userId,
        username: u.username,
        email: u.email,
        fullName: u.fullName
      })) : [];
      setAllUsers(mappedUsers);
    }).catch(() => setAllUsers([]));
  }, [selectedMandateId]);

  // Refresh instance users with optional pagination
  const refreshUsers = useCallback(async (paginationParams?: PaginationParams) => {
    if (selectedMandateId && selectedInstanceId) {
      setUsersLoading(true);
      try {
        // Build query params
        const params = new URLSearchParams();
        if (paginationParams && Object.keys(paginationParams).length > 0) {
          params.append('pagination', JSON.stringify(paginationParams));
        }
        
        const url = params.toString()
          ? `/api/features/instances/${selectedInstanceId}/users?${params.toString()}`
          : `/api/features/instances/${selectedInstanceId}/users`;
        
        const response = await api.get(url, {
          headers: { 'X-Mandate-Id': selectedMandateId }
        });
        
        if (response.data?.items && Array.isArray(response.data.items)) {
          setInstanceUsers(response.data.items);
          if (response.data.pagination) {
            setUsersPagination(response.data.pagination);
          }
        } else {
          const users = Array.isArray(response.data) ? response.data : [];
          setInstanceUsers(users);
        }
      } catch (err) {
        console.error('Error refreshing users:', err);
        setInstanceUsers([]);
      } finally {
        setUsersLoading(false);
      }
    }
  }, [selectedMandateId, selectedInstanceId]);

  // Get users not yet in the instance
  const availableUsers = useMemo(() => {
    const existingUserIds = new Set(instanceUsers.map(u => u.userId));
    return allUsers.filter(u => !existingUserIds.has(u.id));
  }, [allUsers, instanceUsers]);

  // Table columns
  const columns = useMemo(() => [
    {
      key: 'username',
      label: 'Benutzername',
      type: 'text' as const,
      sortable: true,
      filterable: true,
      searchable: true,
      width: 150,
    },
    {
      key: 'email',
      label: 'E-Mail',
      type: 'text' as const,
      sortable: true,
      filterable: true,
      searchable: true,
      width: 200,
    },
    {
      key: 'fullName',
      label: 'Vollständiger Name',
      type: 'text' as const,
      sortable: true,
      filterable: true,
      searchable: true,
      width: 180,
    },
    {
      key: 'roleLabels',
      label: 'Rollen',
      type: 'text' as const,
      sortable: false,
      filterable: false,
      searchable: true,
      width: 200,
      render: (value: string[]) => {
        if (!value || value.length === 0) return '-';
        return value.join(', ');
      },
    },
    {
      key: 'enabled',
      label: 'Aktiv',
      type: 'boolean' as const,
      sortable: true,
      filterable: true,
      searchable: false,
      width: 80,
    },
  ], []);

  // Dynamic options for forms (users and roles)
  const userOptions = useMemo(() => 
    availableUsers.map(u => ({
      value: u.id,
      label: `${u.username} ${u.email ? `(${u.email})` : ''}`
    })), [availableUsers]);
  
  const roleOptions = useMemo(() => 
    instanceRoles.map(r => ({
      value: r.id,
      label: r.roleLabel
    })), [instanceRoles]);

  // Form attributes for adding a user
  const addUserFields: AttributeDefinition[] = useMemo(() => {
    return [
      {
        name: 'userId',
        label: 'Benutzer',
        type: 'enum' as const,
        required: true,
        options: userOptions,
      },
      {
        name: 'roleIds',
        label: 'Rollen',
        type: 'multiselect' as const,
        required: true,
        options: roleOptions,
      }
    ];
  }, [userOptions, roleOptions]);

  // Form attributes for editing user roles
  const editRolesFields: AttributeDefinition[] = useMemo(() => {
    return [{
      name: 'roleIds',
      label: 'Rollen',
      type: 'multiselect' as const,
      required: true,
      options: roleOptions,
    }];
  }, [roleOptions]);

  // Handle add user submit
  const handleAddUser = async (data: { userId: string; roleIds: string[] }) => {
    if (!selectedMandateId || !selectedInstanceId) return;
    setIsSubmitting(true);
    try {
      const result = await addUserToInstance(selectedMandateId, selectedInstanceId, data);
      if (result.success) {
        setShowAddModal(false);
        refreshUsers();
        showSuccess('Benutzer hinzugefügt', 'Der Benutzer wurde erfolgreich zur Feature-Instanz hinzugefügt.');
      } else {
        showError('Fehler', result.error || 'Fehler beim Hinzufügen des Benutzers');
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  // Handle edit roles submit
  const handleEditRoles = async (data: { roleIds: string[] }) => {
    if (!selectedMandateId || !selectedInstanceId || !editingUser) return;
    setIsSubmitting(true);
    try {
      const result = await updateInstanceUserRoles(
        selectedMandateId,
        selectedInstanceId,
        editingUser.userId,
        data.roleIds
      );
      if (result.success) {
        setEditingUser(null);
        refreshUsers();
        showSuccess('Rollen aktualisiert', 'Die Benutzerrollen wurden erfolgreich aktualisiert.');
      } else {
        showError('Fehler', result.error || 'Fehler beim Aktualisieren der Rollen');
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  // Handle remove user (confirmation handled by DeleteActionButton)
  const handleRemoveUser = async (user: FeatureAccessUser) => {
    if (!selectedMandateId || !selectedInstanceId) return;
    const result = await removeUserFromInstance(selectedMandateId, selectedInstanceId, user.userId);
    if (result.success) {
      refreshUsers();
      showSuccess('Benutzer entfernt', `"${user.username}" wurde aus der Feature-Instanz entfernt.`);
    } else {
      showError('Fehler', result.error || 'Fehler beim Entfernen des Benutzers');
    }
  };

  // Handle edit click
  const handleEditClick = (user: FeatureAccessUser) => {
    setEditingUser(user);
  };

  // Get feature label
  const getFeatureLabel = (code: string) => {
    const feature = features.find(f => f.code === code);
    if (feature) {
      return typeof feature.label === 'object'
        ? (feature.label.de || feature.label.en || code)
        : (feature.label || code);
    }
    return code;
  };

  // Get selected instance info from combined options
  const selectedInstance = useMemo(() => {
    const option = combinedOptions.find(o => o.combinedKey === selectedCombinedKey);
    if (!option) return null;
    return instances.find(i => i.id === option.instanceId) || {
      id: option.instanceId,
      label: option.instanceLabel,
      featureCode: option.featureCode,
      mandateId: option.mandateId,
    };
  }, [combinedOptions, selectedCombinedKey, instances]);

  // Get selected combined option for display
  const selectedOption = useMemo(() => {
    return combinedOptions.find(o => o.combinedKey === selectedCombinedKey);
  }, [combinedOptions, selectedCombinedKey]);

  if (error && !selectedCombinedKey) {
    return (
      <div className={styles.adminPage}>
        <div className={styles.errorContainer}>
          <span className={styles.errorIcon}>⚠️</span>
          <p className={styles.errorMessage}>Fehler: {error}</p>
          <button className={styles.secondaryButton} onClick={() => fetchFeatures()}>
            <FaSync /> Erneut versuchen
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className={styles.adminPage}>
      <div className={styles.pageHeader}>
        <div>
          <h1 className={styles.pageTitle}>Feature Instanz Benutzer</h1>
          <p className={styles.pageSubtitle}>Verwalten Sie Benutzerzugriffe auf Feature-Instanzen</p>
        </div>
      </div>

      {/* Combined Selector: Mandate + Feature Instance */}
      <div className={styles.filterSection}>
        <div className={styles.filterGroup} style={{ flex: 1, maxWidth: 500 }}>
          <label className={styles.filterLabel}>
            <FaCube style={{ marginRight: 8 }} />
            Mandant / Feature-Instanz:
          </label>
          <select
            className={styles.filterSelect}
            value={selectedCombinedKey}
            onChange={(e) => setSelectedCombinedKey(e.target.value)}
            disabled={loading || combinedOptions.length === 0}
          >
            <option value="">-- Mandant / Feature-Instanz wählen --</option>
            {/* Group options by mandate */}
            {(() => {
              const groupedByMandate: Record<string, CombinedInstanceOption[]> = {};
              combinedOptions.forEach(opt => {
                if (!groupedByMandate[opt.mandateName]) {
                  groupedByMandate[opt.mandateName] = [];
                }
                groupedByMandate[opt.mandateName].push(opt);
              });
              
              return Object.entries(groupedByMandate).map(([mandateName, options]) => (
                <optgroup key={mandateName} label={mandateName}>
                  {options.map(opt => (
                    <option key={opt.combinedKey} value={opt.combinedKey}>
                      {opt.instanceLabel} ({getFeatureLabel(opt.featureCode)})
                    </option>
                  ))}
                </optgroup>
              ));
            })()}
          </select>
        </div>
        
        {selectedCombinedKey && (
          <div className={styles.headerActions}>
            <button
              className={styles.secondaryButton}
              onClick={() => refreshUsers()}
              disabled={usersLoading}
            >
              <FaSync className={usersLoading ? 'spinning' : ''} /> Aktualisieren
            </button>
            <button
              className={styles.primaryButton}
              onClick={() => setShowAddModal(true)}
              disabled={availableUsers.length === 0 || instanceRoles.length === 0}
            >
              <FaPlus /> Benutzer hinzufügen
            </button>
          </div>
        )}
      </div>

      {/* Info box when instance is selected */}
      {selectedOption && (
        <div className={styles.infoBox}>
          <FaBuilding style={{ marginRight: 8 }} />
          <span>Mandant: <strong>{selectedOption.mandateName}</strong></span>
          <span style={{ margin: '0 16px', color: 'var(--color-border)' }}>|</span>
          <FaCube style={{ marginRight: 8 }} />
          <span>Instanz: <strong>{selectedOption.instanceLabel}</strong> ({selectedOption.featureCode})</span>
        </div>
      )}
      
      {/* Roles info box */}
      {selectedInstance && instanceRoles.length > 0 && (
        <div className={styles.infoBox}>
          <span>Verfügbare Rollen: </span>
          {instanceRoles.map((r, i) => (
            <span key={r.id}>
              {i > 0 && ', '}
              <strong>{r.roleLabel}</strong>
            </span>
          ))}
        </div>
      )}

      {/* Warning if no roles available */}
      {selectedInstance && instanceRoles.length === 0 && !usersLoading && (
        <div className={styles.warningBox || styles.infoBox}>
          <span>⚠️ </span>
          <span>Diese Instanz hat noch keine Rollen. Bitte synchronisieren Sie die Rollen zuerst unter "Feature-Instanzen".</span>
        </div>
      )}

      {/* Content */}
      {!selectedCombinedKey ? (
        <div className={styles.emptyState}>
          <FaCube className={styles.emptyIcon} />
          <h3 className={styles.emptyTitle}>Keine Feature-Instanz ausgewählt</h3>
          <p className={styles.emptyDescription}>
            {combinedOptions.length === 0 
              ? 'Es gibt noch keine Feature-Instanzen. Erstellen Sie zuerst Feature-Instanzen unter "Feature-Instanzen".' 
              : 'Wählen Sie eine Feature-Instanz aus, um deren Benutzer zu verwalten.'}
          </p>
        </div>
      ) : usersLoading && instanceUsers.length === 0 ? (
        <div className={styles.loadingContainer}>
          <div className={styles.spinner} />
          <span>Lade Benutzer...</span>
        </div>
      ) : instanceUsers.length === 0 ? (
        <div className={styles.emptyState}>
          <FaUsers className={styles.emptyIcon} />
          <h3 className={styles.emptyTitle}>Keine Benutzer</h3>
          <p className={styles.emptyDescription}>
            Dieser Feature-Instanz sind noch keine Benutzer zugewiesen.
          </p>
          <button
            className={styles.primaryButton}
            onClick={() => setShowAddModal(true)}
            disabled={availableUsers.length === 0 || instanceRoles.length === 0}
          >
            <FaPlus /> Ersten Benutzer hinzufügen
          </button>
        </div>
      ) : (
        <div className={styles.tableContainer}>
          <FormGeneratorTable
            data={instanceUsers}
            columns={columns}
            loading={usersLoading}
            pagination={true}
            pageSize={25}
            searchable={true}
            filterable={true}
            sortable={true}
            selectable={false}
            actionButtons={[
              {
                type: 'edit' as const,
                onAction: handleEditClick,
                title: 'Rollen bearbeiten',
              },
              {
                type: 'delete' as const,
                title: 'Aus Instanz entfernen',
              }
            ]}
            onDelete={handleRemoveUser}
            hookData={{
              refetch: refreshUsers,
              pagination: usersPagination,
              handleDelete: async (featureAccessId: string) => {
                // Find user by FeatureAccess ID to get userId for API call
                const user = instanceUsers.find(u => u.id === featureAccessId);
                if (user) {
                  const result = await removeUserFromInstance(selectedMandateId, selectedInstanceId, user.userId);
                  return result.success;
                }
                return false;
              },
            }}
            emptyMessage="Keine Benutzer gefunden"
          />
        </div>
      )}

      {/* Add User Modal */}
      {showAddModal && (
        <div className={styles.modalOverlay} onClick={() => setShowAddModal(false)}>
          <div className={styles.modal} onClick={e => e.stopPropagation()}>
            <div className={styles.modalHeader}>
              <h2 className={styles.modalTitle}>Benutzer zur Feature-Instanz hinzufügen</h2>
              <button
                className={styles.modalClose}
                onClick={() => setShowAddModal(false)}
              >
                ✕
              </button>
            </div>
            <div className={styles.modalContent}>
              {availableUsers.length === 0 ? (
                <p>Alle Benutzer haben bereits Zugriff auf diese Feature-Instanz.</p>
              ) : instanceRoles.length === 0 ? (
                <p>Diese Feature-Instanz hat keine Rollen. Bitte synchronisieren Sie zuerst die Rollen.</p>
              ) : (
                <FormGeneratorForm
                  attributes={addUserFields}
                  mode="create"
                  onSubmit={handleAddUser}
                  onCancel={() => setShowAddModal(false)}
                  submitButtonText="Hinzufügen"
                  cancelButtonText="Abbrechen"
                />
              )}
            </div>
          </div>
        </div>
      )}

      {/* Edit Roles Modal */}
      {editingUser && (
        <div className={styles.modalOverlay} onClick={() => setEditingUser(null)}>
          <div className={styles.modal} onClick={e => e.stopPropagation()}>
            <div className={styles.modalHeader}>
              <h2 className={styles.modalTitle}>Rollen bearbeiten: {editingUser.username}</h2>
              <button
                className={styles.modalClose}
                onClick={() => setEditingUser(null)}
              >
                ✕
              </button>
            </div>
            <div className={styles.modalContent}>
              <FormGeneratorForm
                attributes={editRolesFields}
                data={{ roleIds: editingUser.roleIds }}
                mode="edit"
                onSubmit={handleEditRoles}
                onCancel={() => setEditingUser(null)}
                submitButtonText="Speichern"
                cancelButtonText="Abbrechen"
              />
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default AdminFeatureInstanceUsersPage;
