/**
 * AccessManagementHub
 *
 * Central admin page for feature instance access management.
 * Shows mandate/feature context, overview stats, instance cards, and relationship diagram.
 */

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { Link } from 'react-router-dom';
import {
  useFeatureAccess,
  type FeatureInstance,
  type Feature,
  type FeatureAccessUser,
} from '../../hooks/useFeatureAccess';
import { useUserMandates, type Mandate } from '../../hooks/useUserMandates';
import { FaBuilding, FaCube, FaUsers, FaCogs, FaSync, FaChartBar, FaLink, FaList, FaSitemap } from 'react-icons/fa';
import { useToast } from '../../contexts/ToastContext';
import api from '../../api';
import styles from './Admin.module.css';
import hubStyles from './AccessManagementHub.module.css';
import { InstanceDetailModal } from './InstanceDetailModal';
import { FeatureInstanceWizard } from './wizards/FeatureInstanceWizard';
import { InstanceHierarchyView } from './InstanceHierarchyView';

import { useLanguage } from '../../providers/language/LanguageContext';

function getMandateName(mandate: Mandate): string {
  if (mandate.label) return mandate.label;
  if (typeof mandate.name === 'object') {
    return mandate.name.de || mandate.name.en || Object.values(mandate.name)[0] || mandate.id;
  }
  return mandate.name || mandate.id;
}

function getFeatureLabel(feature: Feature): string {
  if (typeof feature.label === 'object') {
    return feature.label.de || feature.label.en || feature.code;
  }
  return feature.label || feature.code;
}

export interface InstanceWithStats extends FeatureInstance {
  userCount?: number;
  roleCount?: number;
}

export const AccessManagementHub: React.FC = () => {
    const { t } = useLanguage();

  const {
    features,
    instances,
    loading,
    error,
    fetchFeatures,
    fetchInstances,
    syncInstanceRoles,
  } = useFeatureAccess();
  const { fetchMandates } = useUserMandates();
  const { showSuccess, showError } = useToast();

  const [mandates, setMandates] = useState<Mandate[]>([]);
  const [selectedMandateId, setSelectedMandateId] = useState<string>('');
  const [selectedFeatureCode, setSelectedFeatureCode] = useState<string>('');
  const [instancesWithStats, setInstancesWithStats] = useState<InstanceWithStats[]>([]);
  const [statsLoading, setStatsLoading] = useState(false);
  const [detailInstance, setDetailInstance] = useState<{
    instance: FeatureInstance;
    mandateId: string;
    mandateName: string;
    featureLabel: string;
  } | null>(null);
  const [showWizard, setShowWizard] = useState(false);
  type ViewMode = 'list' | 'hierarchy';
  const [viewMode, setViewMode] = useState<ViewMode>('hierarchy');
  const [instanceUsersMap, setInstanceUsersMap] = useState<Record<string, FeatureAccessUser[]>>({});
  const [hierarchyUsersLoading, setHierarchyUsersLoading] = useState(false);
  const [instancesByMandate, setInstancesByMandate] = useState<Record<string, InstanceWithStats[]>>({});

  useEffect(() => {
    fetchFeatures();
    fetchMandates().then(data => {
      setMandates(data);
      if (data.length > 0 && !selectedMandateId) {
        setSelectedMandateId(data[0].id);
      }
    });
  }, [fetchFeatures, fetchMandates]);

  useEffect(() => {
    if (selectedMandateId) {
      fetchInstances(selectedMandateId, selectedFeatureCode || undefined);
    } else {
      setInstancesWithStats([]);
    }
  }, [selectedMandateId, selectedFeatureCode, fetchInstances]);

  const loadInstanceStats = useCallback(async (mandateId: string, instanceList: FeatureInstance[]) => {
    if (instanceList.length === 0) {
      setInstancesWithStats([]);
      return;
    }
    setStatsLoading(true);
    try {
      const results = await Promise.all(
        instanceList.map(async (inst) => {
          try {
            const [usersRes, rolesRes] = await Promise.all([
              api.get(`/api/features/instances/${inst.id}/users`, {
                headers: { 'X-Mandate-Id': mandateId },
              }),
              api.get(`/api/features/instances/${inst.id}/available-roles`, {
                headers: { 'X-Mandate-Id': mandateId },
              }),
            ]);
            const users = Array.isArray(usersRes.data) ? usersRes.data : usersRes.data?.items || [];
            const roles = Array.isArray(rolesRes.data) ? rolesRes.data : [];
            return {
              ...inst,
              userCount: users.length,
              roleCount: roles.length,
            };
          } catch {
            return { ...inst, userCount: 0, roleCount: 0 };
          }
        })
      );
      setInstancesWithStats(results);
    } catch {
      setInstancesWithStats(instanceList.map((i) => ({ ...i, userCount: 0, roleCount: 0 })));
    } finally {
      setStatsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (selectedMandateId && instances.length > 0 && !loading) {
      loadInstanceStats(selectedMandateId, instances);
    } else if (instances.length === 0) {
      setInstancesWithStats([]);
    }
  }, [selectedMandateId, instances, loading, loadInstanceStats]);

  const handleSyncRoles = async (instance: FeatureInstance) => {
    if (!selectedMandateId) return;
    try {
      const result = await syncInstanceRoles(selectedMandateId, instance.id, true);
      if (result.success && result.data) {
        showSuccess(
          'Rollen synchronisiert',
          `Hinzugefügt: ${result.data.added}, Entfernt: ${result.data.removed}, Unverändert: ${result.data.unchanged}`
        );
        fetchInstances(selectedMandateId, selectedFeatureCode || undefined);
      } else {
        showError('Synchronisierung fehlgeschlagen', result.error || 'Fehler beim Synchronisieren');
      }
    } catch {
      showError('Fehler', 'Rollen konnten nicht synchronisiert werden');
    }
  };

  const handleOpenDetail = (instance: FeatureInstance, mandateIdOverride?: string) => {
    const mandateId = mandateIdOverride ?? selectedMandateId;
    const mandate = mandates.find((m) => m.id === mandateId);
    const feature = features.find((f) => f.code === instance.featureCode);
    setDetailInstance({
      instance,
      mandateId: mandateId || '',
      mandateName: mandate ? getMandateName(mandate) : mandateId || '',
      featureLabel: feature ? getFeatureLabel(feature) : instance.featureCode,
    });
  };

  const handleCloseDetail = () => {
    setDetailInstance(null);
  };

  const handleDetailSaved = () => {
    if (selectedMandateId) {
      fetchInstances(selectedMandateId, selectedFeatureCode || undefined);
    }
    setDetailInstance(null);
  };

  const handleWizardComplete = () => {
    setShowWizard(false);
    if (selectedMandateId) {
      fetchInstances(selectedMandateId, selectedFeatureCode || undefined);
    }
  };

  const filteredInstances = useMemo(() => {
    if (!selectedFeatureCode) return instancesWithStats;
    return instancesWithStats.filter((i) => i.featureCode === selectedFeatureCode);
  }, [instancesWithStats, selectedFeatureCode]);

  const loadAllHierarchyData = useCallback(async () => {
    if (mandates.length === 0) {
      setInstancesByMandate({});
      setInstanceUsersMap({});
      return;
    }
    setHierarchyUsersLoading(true);
    try {
      const mandateIds = mandates.map((m) => m.id);
      const instancesResults = await Promise.all(
        mandateIds.map(async (mandateId) => {
          try {
            const res = await api.get('/api/features/instances', {
              headers: { 'X-Mandate-Id': mandateId },
            });
            const list = res.data?.items ?? (Array.isArray(res.data) ? res.data : []);
            return { mandateId, instances: list as FeatureInstance[] };
          } catch {
            return { mandateId, instances: [] as FeatureInstance[] };
          }
        })
      );
      const byMandate: Record<string, InstanceWithStats[]> = {};
      const allInstanceIds: { instanceId: string; mandateId: string }[] = [];
      for (const { mandateId, instances } of instancesResults) {
        const withStats = await Promise.all(
          instances.map(async (inst) => {
            try {
              const [usersRes, rolesRes] = await Promise.all([
                api.get(`/api/features/instances/${inst.id}/users`, {
                  headers: { 'X-Mandate-Id': mandateId },
                }),
                api.get(`/api/features/instances/${inst.id}/available-roles`, {
                  headers: { 'X-Mandate-Id': mandateId },
                }),
              ]);
              const users = Array.isArray(usersRes.data) ? usersRes.data : usersRes.data?.items ?? [];
              const roles = Array.isArray(rolesRes.data) ? rolesRes.data : [];
              allInstanceIds.push({ instanceId: inst.id, mandateId });
              return {
                ...inst,
                userCount: users.length,
                roleCount: roles.length,
              } as InstanceWithStats;
            } catch {
              allInstanceIds.push({ instanceId: inst.id, mandateId });
              return { ...inst, userCount: 0, roleCount: 0 } as InstanceWithStats;
            }
          })
        );
        byMandate[mandateId] = withStats;
      }
      setInstancesByMandate(byMandate);
      const usersMap: Record<string, FeatureAccessUser[]> = {};
      await Promise.all(
        allInstanceIds.map(async ({ instanceId, mandateId }) => {
          try {
            const res = await api.get(`/api/features/instances/${instanceId}/users`, {
              headers: { 'X-Mandate-Id': mandateId },
            });
            const users = Array.isArray(res.data) ? res.data : res.data?.items ?? [];
            usersMap[instanceId] = users as FeatureAccessUser[];
          } catch {
            usersMap[instanceId] = [];
          }
        })
      );
      setInstanceUsersMap(usersMap);
    } finally {
      setHierarchyUsersLoading(false);
    }
  }, [mandates]);

  useEffect(() => {
    if (viewMode === 'hierarchy' && mandates.length > 0) {
      loadAllHierarchyData();
    } else if (viewMode !== 'hierarchy') {
      setInstancesByMandate({});
      setInstanceUsersMap({});
    }
  }, [viewMode, mandates, loadAllHierarchyData]);

  const overviewStats = useMemo(() => {
    const totalUsers = filteredInstances.reduce((sum, i) => sum + (i.userCount ?? 0), 0);
    const maxRoles = Math.max(0, ...filteredInstances.map((i) => i.roleCount ?? 0));
    return {
      instances: filteredInstances.length,
      users: totalUsers,
      roles: maxRoles,
    };
  }, [filteredInstances]);

  const relationshipData = useMemo(() => {
    if (!selectedMandateId || filteredInstances.length === 0) return null;
    const mandate = mandates.find((m) => m.id === selectedMandateId);
    return {
      mandateName: mandate ? getMandateName(mandate) : selectedMandateId,
      instances: filteredInstances.map((inst) => {
        const feature = features.find((f) => f.code === inst.featureCode);
        return {
          id: inst.id,
          label: inst.label,
          featureLabel: feature ? getFeatureLabel(feature) : inst.featureCode,
          userCount: inst.userCount ?? 0,
        };
      }),
    };
  }, [selectedMandateId, mandates, filteredInstances, features]);

  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={() => fetchFeatures()}>
            <FaSync /> Erneut versuchen
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className={styles.adminPage}>
      <div className={styles.pageHeader}>
        <div>
          <h1 className={styles.pageTitle}>Zugriffsverwaltung</h1>
          <p className={styles.pageSubtitle}>
            Feature-Instanzen, Benutzer und Rollen an einem Ort verwalten
          </p>
        </div>
      </div>

      <div className={hubStyles.filters}>
        {/* Filter dropdowns only shown in list view - hierarchy shows everything */}
        {viewMode === 'list' && (
          <>
            <div className={styles.filterGroup}>
              <label className={styles.filterLabel}>
                <FaBuilding style={{ marginRight: 8 }} />
                Mandant:
              </label>
              <select
                className={styles.filterSelect}
                value={selectedMandateId}
                onChange={(e) => setSelectedMandateId(e.target.value)}
              >
                <option value="">{t('accessManagementHub.mandantWaehlen')}</option>
                {mandates.map((m) => (
                  <option key={m.id} value={m.id}>
                    {getMandateName(m)}
                  </option>
                ))}
              </select>
            </div>
            <div className={styles.filterGroup}>
              <label className={styles.filterLabel}>
                <FaCube style={{ marginRight: 8 }} />
                Feature:
              </label>
              <select
                className={styles.filterSelect}
                value={selectedFeatureCode}
                onChange={(e) => setSelectedFeatureCode(e.target.value)}
              >
                <option value="">{t('accessManagementHub.alle')}</option>
                {features.map((f) => (
                  <option key={f.code} value={f.code}>
                    {getFeatureLabel(f)}
                  </option>
                ))}
              </select>
            </div>
            {selectedMandateId && (
              <div className={styles.headerActions}>
                <button
                  className={styles.secondaryButton}
                  onClick={() =>
                    fetchInstances(selectedMandateId, selectedFeatureCode || undefined)
                  }
                  disabled={loading}
                >
                  <FaSync className={loading ? 'spinning' : ''} /> Aktualisieren
                </button>
                <button
                  className={styles.primaryButton}
                  onClick={() => setShowWizard(true)}
                  disabled={features.length === 0}
                >
                  + Neue Instanz erstellen
                </button>
              </div>
            )}
          </>
        )}
      </div>

      <div className={hubStyles.viewModeSwitch}>
        <div className={hubStyles.viewModeButtons}>
          <button
            type="button"
            className={viewMode === 'list' ? hubStyles.viewModeActive : hubStyles.viewModeButton}
            onClick={() => setViewMode('list')}
          >
            <FaList /> Listenansicht
          </button>
          <button
            type="button"
            className={viewMode === 'hierarchy' ? hubStyles.viewModeActive : hubStyles.viewModeButton}
            onClick={() => setViewMode('hierarchy')}
          >
            <FaSitemap /> Hierarchie
          </button>
        </div>
        <Link to="/admin/mandates" className={hubStyles.mandatesLink}>
          <FaBuilding /> Mandanten verwalten
        </Link>
        <Link to="/admin/user-mandates" className={hubStyles.mandatesLink}>
          <FaUsers /> Mandant-Benutzer
        </Link>
      </div>

      {viewMode === 'hierarchy' ? (
        <InstanceHierarchyView
          mandates={mandates}
          getMandateName={getMandateName}
          instancesByMandate={instancesByMandate}
          instanceUsersMap={instanceUsersMap}
          features={features}
          getFeatureLabel={getFeatureLabel}
          loading={hierarchyUsersLoading}
          onOpenDetail={handleOpenDetail}
        />
      ) : !selectedMandateId ? (
        <div className={styles.emptyState}>
          <FaBuilding className={styles.emptyIcon} />
          <h3 className={styles.emptyTitle}>{t('accessManagementHub.keinMandantAusgewaehlt')}</h3>
          <p className={styles.emptyDescription}>
            Wählen Sie einen Mandanten, um dessen Feature-Instanzen und Zugriffe zu verwalten.
          </p>
        </div>
      ) : (
        <>
          <div className={hubStyles.overviewRow}>
            <div className={hubStyles.statsCard}>
              <FaChartBar className={hubStyles.statsIcon} />
              <div className={hubStyles.statsContent}>
                <span className={hubStyles.statsValue}>
                  {loading || statsLoading ? '…' : overviewStats.instances}
                </span>
                <span className={hubStyles.statsLabel}>Instanzen</span>
              </div>
            </div>
            <div className={hubStyles.statsCard}>
              <FaUsers className={hubStyles.statsIcon} />
              <div className={hubStyles.statsContent}>
                <span className={hubStyles.statsValue}>
                  {loading || statsLoading ? '…' : overviewStats.users}
                </span>
                <span className={hubStyles.statsLabel}>{t('accessManagementHub.benutzer')}</span>
              </div>
            </div>
            <div className={hubStyles.statsCard}>
              <FaCogs className={hubStyles.statsIcon} />
              <div className={hubStyles.statsContent}>
                <span className={hubStyles.statsValue}>
                  {loading || statsLoading ? '…' : overviewStats.roles}
                </span>
                <span className={hubStyles.statsLabel}>{t('accessManagementHub.rollenMax')}</span>
              </div>
            </div>
            {relationshipData && relationshipData.instances.length > 0 && (
              <div className={hubStyles.diagramCard}>
                <FaLink className={hubStyles.statsIcon} />
                <div className={hubStyles.diagramContent}>
                  <span className={hubStyles.diagramTitle}>Beziehungen</span>
                  <div className={hubStyles.diagramFlow}>
                    <div className={hubStyles.diagramNode}>{relationshipData.mandateName}</div>
                    <div className={hubStyles.diagramNodes}>
                      {relationshipData.instances.slice(0, 5).map((inst) => (
                        <div key={inst.id} className={hubStyles.diagramNodeSmall}>
                          {inst.label} ({inst.userCount})
                        </div>
                      ))}
                      {relationshipData.instances.length > 5 && (
                        <div className={hubStyles.diagramNodeSmall}>
                          +{relationshipData.instances.length - 5} weitere
                        </div>
                      )}
                    </div>
                  </div>
                </div>
              </div>
            )}
          </div>

          <section className={hubStyles.section}>
            <h2 className={hubStyles.sectionTitle}>Feature-Instanzen</h2>
            {loading && filteredInstances.length === 0 ? (
              <div className={styles.loadingContainer}>
                <div className={styles.spinner} />
                <span>{t('accessManagementHub.ladeInstanzen')}</span>
              </div>
            ) : filteredInstances.length === 0 ? (
              <div className={styles.emptyState}>
                <FaCube className={styles.emptyIcon} />
                <h3 className={styles.emptyTitle}>{t('accessManagementHub.keineFeatureinstanzen')}</h3>
                <p className={styles.emptyDescription}>
                  Erstellen Sie eine neue Instanz oder wählen Sie ein anderes Feature.
                </p>
                <button
                  className={styles.primaryButton}
                  onClick={() => setShowWizard(true)}
                  disabled={features.length === 0}
                >
                  + Erste Instanz erstellen
                </button>
              </div>
            ) : (
              <div className={hubStyles.instanceGrid}>
                {filteredInstances.map((inst) => (
                  <div key={inst.id} className={hubStyles.instanceCard}>
                    <div className={hubStyles.instanceCardHeader}>
                      <span className={hubStyles.instanceLabel}>{inst.label}</span>
                      <span
                        className={`${hubStyles.instanceBadge} ${inst.enabled ? hubStyles.badgeActive : hubStyles.badgeInactive}`}
                      >
                        {inst.enabled ? t('accessManagementHub.aktiv') : t('accessManagementHub.inaktiv')}
                      </span>
                    </div>
                    <div className={hubStyles.instanceMeta}>
                      <span>{getFeatureLabel(features.find((f) => f.code === inst.featureCode) || { code: inst.featureCode, label: inst.featureCode })}</span>
                      <span>{inst.userCount ?? '—'} Benutzer</span>
                      <span>{inst.roleCount ?? '—'} Rollen</span>
                    </div>
                    <div className={hubStyles.instanceActions}>
                      <button
                        type="button"
                        className={hubStyles.cardAction}
                        onClick={() => handleOpenDetail(inst, selectedMandateId)}
                      >
                        <FaUsers /> Benutzer verwalten
                      </button>
                      <button
                        type="button"
                        className={hubStyles.cardAction}
                        onClick={() => handleSyncRoles(inst)}
                        disabled={!inst.enabled}
                        title={t('accessManagementHub.rollenSynchronisieren')}
                      >
                        <FaCogs /> Rollen sync
                      </button>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </section>
        </>
      )}

      {detailInstance && (
        <InstanceDetailModal
          instance={detailInstance.instance}
          mandateId={detailInstance.mandateId}
          mandateName={detailInstance.mandateName}
          featureLabel={detailInstance.featureLabel}
          onClose={handleCloseDetail}
          onSaved={handleDetailSaved}
        />
      )}

      {showWizard && (
        <FeatureInstanceWizard
          mandateId={selectedMandateId}
          mandates={mandates}
          features={features}
          onClose={() => setShowWizard(false)}
          onComplete={handleWizardComplete}
        />
      )}
    </div>
  );
};

export default AccessManagementHub;
