/**
 * AdminUserMandatesPage
 * 
 * Admin page for managing user-mandate memberships.
 * Allows assigning users to mandates and managing their roles within mandates.
 */

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

export const AdminUserMandatesPage: React.FC = () => {
  const { showError } = useToast();
  const {
    users,
    loading,
    error,
    pagination,
    fetchMandateUsers,
    addUserToMandate,
    removeUserFromMandate,
    updateUserRoles,
    fetchMandates,
    fetchRoles,
    fetchAllUsers,
  } = useUserMandates();
  
  // Store current mandateId for refetch
  const currentMandateIdRef = useRef<string>('');

  // State
  const [mandates, setMandates] = useState<Mandate[]>([]);
  const [selectedMandateId, setSelectedMandateId] = useState<string>('');
  const [roles, setRoles] = useState<Role[]>([]);
  const [allUsers, setAllUsers] = useState<Array<{ id: string; username: string; email?: string; fullName?: string }>>([]);
  const [showAddModal, setShowAddModal] = useState(false);
  const [editingUser, setEditingUser] = useState<MandateUser | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [backendAttributes, setBackendAttributes] = useState<AttributeDefinition[]>([]);

  // Load mandates and attributes on mount
  useEffect(() => {
    const loadMandates = async () => {
      const data = await fetchMandates();
      setMandates(data);
      // Auto-select first mandate if available
      if (data.length > 0 && !selectedMandateId) {
        setSelectedMandateId(data[0].id);
      }
    };
    loadMandates();
    // Fetch UserMandate attributes from backend (for table columns)
    api.get('/api/attributes/UserMandate').then(response => {
      const attrs = response.data?.attributes || response.data || [];
      setBackendAttributes(Array.isArray(attrs) ? attrs : []);
    }).catch(() => setBackendAttributes([]));
  }, [fetchMandates]);

  // Load users when mandate changes
  useEffect(() => {
    if (selectedMandateId) {
      currentMandateIdRef.current = selectedMandateId;
      fetchMandateUsers(selectedMandateId);
      fetchRoles(selectedMandateId).then(setRoles);
    }
  }, [selectedMandateId, fetchMandateUsers, fetchRoles]);

  // Refetch wrapper that accepts pagination params from FormGeneratorTable
  const refetchWithParams = useCallback(async (paginationParams?: PaginationParams) => {
    const mandateId = currentMandateIdRef.current;
    if (!mandateId) return;
    // If pagination params provided, pass them; otherwise just use mandateId
    if (paginationParams && Object.keys(paginationParams).length > 0) {
      return fetchMandateUsers(paginationParams);
    }
    return fetchMandateUsers(mandateId);
  }, [fetchMandateUsers]);

  // Load all users for the add modal
  useEffect(() => {
    fetchAllUsers().then(setAllUsers);
  }, [fetchAllUsers]);

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

  // Table columns - based on MandateUserInfo response structure
  const columns = useMemo(() => {
    return [
      {
        key: 'username',
        label: 'Benutzername',
        type: 'text' as any,
        sortable: true,
        filterable: true,
        searchable: true,
        width: 150,
      },
      {
        key: 'email',
        label: 'E-Mail',
        type: 'text' as any,
        sortable: true,
        filterable: true,
        searchable: true,
        width: 200,
      },
      {
        key: 'fullName',
        label: 'Vollständiger Name',
        type: 'text' as any,
        sortable: true,
        filterable: true,
        searchable: true,
        width: 180,
      },
      {
        key: 'roleLabels',
        label: 'Rollen',
        type: 'text' as any,
        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 any,
        sortable: true,
        filterable: true,
        searchable: false,
        width: 80,
      },
    ];
  }, []); // No dependencies - columns are static, roleLabels come from backend

  // 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(() => 
    roles.filter(r => !r.featureInstanceId).map(r => ({
      value: r.id,
      label: r.roleLabel
    })), [roles]);

  // Form attributes for adding a user - uses dynamic options
  // Note: This is an operational form for junction table, not direct model editing
  const addUserFields: AttributeDefinition[] = useMemo(() => {
    // Check if backend has userId attribute to get label/description
    const userIdAttr = backendAttributes.find(a => a.name === 'userId');
    const roleIdsAttr = backendAttributes.find(a => a.name === 'roleIds');
    
    return [
      {
        name: 'targetUserId',
        label: userIdAttr?.label || 'Benutzer',
        type: 'enum' as any,
        required: true,
        options: userOptions,
      },
      {
        name: 'roleIds',
        label: roleIdsAttr?.label || 'Rollen',
        type: 'multiselect' as any,
        required: true,
        options: roleOptions,
      }
    ];
  }, [userOptions, roleOptions, backendAttributes]);

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

  // Handle add user submit
  const handleAddUser = async (data: { targetUserId: string; roleIds: string[] }) => {
    if (!selectedMandateId) return;
    setIsSubmitting(true);
    try {
      const result = await addUserToMandate(selectedMandateId, data);
      if (result.success) {
        setShowAddModal(false);
        fetchMandateUsers(selectedMandateId);
      } 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 || !editingUser) return;
    setIsSubmitting(true);
    try {
      const result = await updateUserRoles(selectedMandateId, editingUser.userId, data.roleIds);
      if (result.success) {
        setEditingUser(null);
        fetchMandateUsers(selectedMandateId);
      } else {
        showError('Fehler', result.error || 'Fehler beim Aktualisieren der Rollen');
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  // Handle remove user (confirmation handled by DeleteActionButton)
  const handleRemoveUser = async (user: MandateUser) => {
    if (!selectedMandateId) return;
    const result = await removeUserFromMandate(selectedMandateId, user.userId);
    if (!result.success) {
      showError('Fehler', result.error || 'Fehler beim Entfernen des Benutzers');
    }
  };

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

  // Get mandate name
  const getMandateName = (mandate: Mandate) => {
    if (typeof mandate.name === 'object') {
      return mandate.name.de || mandate.name.en || Object.values(mandate.name)[0] || mandate.id;
    }
    return mandate.name || mandate.id;
  };

  if (error && !selectedMandateId) {
    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={() => fetchMandates()}>
            <FaSync /> Erneut versuchen
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className={styles.adminPage}>
      <div className={styles.pageHeader}>
        <div>
          <h1 className={styles.pageTitle}>Mandanten-Mitglieder</h1>
          <p className={styles.pageSubtitle}>Verwalten Sie, welche Benutzer Zugriff auf welche Mandanten haben</p>
        </div>
      </div>

      {/* Mandate Selector */}
      <div className={styles.filterSection}>
        <div className={styles.filterGroup}>
          <label className={styles.filterLabel}>
            <FaBuilding style={{ marginRight: 8 }} />
            Mandant auswählen:
          </label>
          <select
            className={styles.filterSelect}
            value={selectedMandateId}
            onChange={(e) => setSelectedMandateId(e.target.value)}
          >
            <option value="">-- Mandant wählen --</option>
            {mandates.map(m => (
              <option key={m.id} value={m.id}>
                {getMandateName(m)}
              </option>
            ))}
          </select>
        </div>
        
        {selectedMandateId && (
          <div className={styles.headerActions}>
            <button
              className={styles.secondaryButton}
              onClick={() => fetchMandateUsers(selectedMandateId)}
              disabled={loading}
            >
              <FaSync className={loading ? 'spinning' : ''} /> Aktualisieren
            </button>
            <button
              className={styles.primaryButton}
              onClick={() => setShowAddModal(true)}
              disabled={availableUsers.length === 0}
            >
              <FaPlus /> Benutzer hinzufügen
            </button>
          </div>
        )}
      </div>

      {/* Content */}
      {!selectedMandateId ? (
        <div className={styles.emptyState}>
          <FaBuilding className={styles.emptyIcon} />
          <h3 className={styles.emptyTitle}>Kein Mandant ausgewählt</h3>
          <p className={styles.emptyDescription}>
            Wählen Sie einen Mandanten aus, um dessen Mitglieder zu verwalten.
          </p>
        </div>
      ) : loading && users.length === 0 ? (
        <div className={styles.loadingContainer}>
          <div className={styles.spinner} />
          <span>Lade Mandanten-Mitglieder...</span>
        </div>
      ) : users.length === 0 ? (
        <div className={styles.emptyState}>
          <FaUsers className={styles.emptyIcon} />
          <h3 className={styles.emptyTitle}>Keine Mitglieder</h3>
          <p className={styles.emptyDescription}>
            Diesem Mandanten sind noch keine Benutzer zugewiesen.
          </p>
          <button
            className={styles.primaryButton}
            onClick={() => setShowAddModal(true)}
            disabled={availableUsers.length === 0}
          >
            <FaPlus /> Ersten Benutzer hinzufügen
          </button>
        </div>
      ) : (
        <div className={styles.tableContainer}>
          <FormGeneratorTable
            data={users}
            columns={columns}
            loading={loading}
            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 Mandant entfernen',
              }
            ]}
            onDelete={handleRemoveUser}
            hookData={{
              refetch: refetchWithParams,
              pagination: pagination,
              handleDelete: async (userMandateId: string) => {
                // Find user by UserMandate ID to get userId for API call
                const user = users.find(u => u.id === userMandateId);
                if (user) {
                  const result = await removeUserFromMandate(selectedMandateId, user.userId);
                  return result.success;
                }
                return false;
              },
            }}
            emptyMessage="Keine Mitglieder 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 zum Mandanten hinzufügen</h2>
              <button
                className={styles.modalClose}
                onClick={() => setShowAddModal(false)}
              >
                ✕
              </button>
            </div>
            <div className={styles.modalContent}>
              {availableUsers.length === 0 ? (
                <p>Alle Benutzer sind bereits diesem Mandanten zugewiesen.</p>
              ) : roleOptions.length === 0 ? (
                <div className={styles.loadingContainer}>
                  <div className={styles.spinner} />
                  <span>Lade Rollen...</span>
                </div>
              ) : (
                <FormGeneratorForm
                  attributes={addUserFields}
                  mode="create"
                  onSubmit={handleAddUser}
                  onCancel={() => setShowAddModal(false)}
                  submitButtonText={isSubmitting ? 'Hinzufügen...' : '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={isSubmitting ? 'Speichern...' : 'Speichern'}
                cancelButtonText="Abbrechen"
              />
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default AdminUserMandatesPage;
