/**
 * useTrusteeOptions Hook
 * 
 * Zentraler Hook für Trustee-Options (Dropdowns, Label-Auflösung).
 * Lädt Options von den entsprechenden /options Endpoints und cached sie.
 * Unterstützt dynamische Filterung (z.B. Contracts nach Organisation).
 */

import { useState, useCallback, useEffect, useMemo } from 'react';
import api from '../api';
import { useInstanceId } from './useCurrentInstance';

// ============================================================================
// TYPES
// ============================================================================

export interface TrusteeOption {
  value: string;
  label: string;
}

export interface TrusteeOptionsMap {
  users: TrusteeOption[];
  organisations: TrusteeOption[];
  roles: TrusteeOption[];
  contracts: TrusteeOption[];
  documents: TrusteeOption[];
  positions: TrusteeOption[];
}

export type TrusteeOptionEntity = keyof TrusteeOptionsMap;

interface LoadOptionsParams {
  organisationId?: string;
  contractId?: string;
}

// ============================================================================
// HOOK
// ============================================================================

/**
 * Hook für Trustee-Options.
 * 
 * @param autoLoad - Array von Entity-Namen, die automatisch beim Mount geladen werden sollen
 * @returns Options-Map, Lade-Funktion, Label-Getter
 * 
 * @example
 * ```tsx
 * // Auto-load users, organisations und roles
 * const { options, getLabel, loading } = useTrusteeOptions(['users', 'organisations', 'roles']);
 * 
 * // Label für eine userId auflösen
 * const userName = getLabel('users', access.userId);
 * 
 * // Contracts für spezifische Organisation nachladen
 * await loadOptions(['contracts'], { organisationId: 'org-123' });
 * ```
 */
export function useTrusteeOptions(autoLoad: TrusteeOptionEntity[] = []) {
  const instanceId = useInstanceId();
  
  const [options, setOptions] = useState<Partial<TrusteeOptionsMap>>({
    users: [],
    organisations: [],
    roles: [],
    contracts: [],
    documents: [],
    positions: [],
  });
  
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [loadedEntities, setLoadedEntities] = useState<Set<string>>(new Set());

  /**
   * Lädt Options für angegebene Entities.
   * 
   * @param entities - Array von Entity-Namen
   * @param filters - Optionale Filter (z.B. organisationId für Contracts)
   */
  const loadOptions = useCallback(async (
    entities: TrusteeOptionEntity[],
    filters?: LoadOptionsParams
  ): Promise<void> => {
    if (!instanceId && entities.some(e => e !== 'users')) {
      console.warn('useTrusteeOptions: No instanceId available, skipping load for trustee entities');
      return;
    }
    
    setLoading(true);
    setError(null);

    try {
      const promises = entities.map(async (entity) => {
        let url: string;
        
        if (entity === 'users') {
          // Users kommen aus dem globalen API-Endpoint
          url = '/api/users/options';
        } else {
          // Trustee-Entities kommen aus dem Feature-API mit instanceId
          url = `/api/trustee/${instanceId}/${entity}/options`;
          
          // Dynamische Filterung für Contracts nach Organisation
          if (filters?.organisationId && entity === 'contracts') {
            url += `?organisationId=${encodeURIComponent(filters.organisationId)}`;
          }
          
          // Dynamische Filterung für Documents/Positions nach Contract
          if (filters?.contractId && (entity === 'documents' || entity === 'positions')) {
            url += `?contractId=${encodeURIComponent(filters.contractId)}`;
          }
        }
        
        const response = await api.get(url);
        return { entity, data: response.data as TrusteeOption[] };
      });

      const results = await Promise.all(promises);
      
      const newOptions: Partial<TrusteeOptionsMap> = {};
      results.forEach(({ entity, data }) => {
        newOptions[entity] = Array.isArray(data) ? data : [];
      });
      
      setOptions(prev => ({ ...prev, ...newOptions }));
      
      // Merke geladene Entities (nur ohne Filter)
      if (!filters) {
        setLoadedEntities(prev => {
          const newSet = new Set(prev);
          entities.forEach(e => newSet.add(e));
          return newSet;
        });
      }
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || err.message || 'Failed to load options';
      setError(errorMessage);
      console.error('useTrusteeOptions: Error loading options:', err);
    } finally {
      setLoading(false);
    }
  }, [instanceId]);

  /**
   * Gibt das Label für einen Wert zurück.
   * Falls nicht gefunden, wird der Wert selbst zurückgegeben.
   */
  const getLabel = useCallback((entity: TrusteeOptionEntity, value: string | null | undefined): string => {
    if (value === null || value === undefined || value === '') {
      return '-';
    }
    
    const entityOptions = options[entity];
    if (!entityOptions || entityOptions.length === 0) {
      return value;
    }
    
    const found = entityOptions.find(o => o.value === value);
    return found?.label || value;
  }, [options]);

  /**
   * Gibt Options für eine Entity zurück.
   */
  const getOptions = useCallback((entity: TrusteeOptionEntity): TrusteeOption[] => {
    return options[entity] || [];
  }, [options]);

  /**
   * Prüft ob Options für eine Entity geladen wurden.
   */
  const isLoaded = useCallback((entity: TrusteeOptionEntity): boolean => {
    return loadedEntities.has(entity);
  }, [loadedEntities]);

  /**
   * Lädt Options für Contracts einer spezifischen Organisation.
   * Nützlich für abhängige Dropdowns.
   */
  const loadContractsForOrganisation = useCallback(async (organisationId: string): Promise<TrusteeOption[]> => {
    if (!instanceId || !organisationId) {
      return [];
    }
    
    try {
      const url = `/api/trustee/${instanceId}/contracts/options?organisationId=${encodeURIComponent(organisationId)}`;
      const response = await api.get(url);
      const contractOptions = Array.isArray(response.data) ? response.data : [];
      
      // Update Options-State
      setOptions(prev => ({ ...prev, contracts: contractOptions }));
      
      return contractOptions;
    } catch (err) {
      console.error('useTrusteeOptions: Error loading contracts for organisation:', err);
      return [];
    }
  }, [instanceId]);

  /**
   * Erstellt eine Lookup-Map für schnelle Label-Auflösung.
   */
  const createLookupMap = useCallback((entity: TrusteeOptionEntity): Map<string, string> => {
    const map = new Map<string, string>();
    const entityOptions = options[entity] || [];
    entityOptions.forEach(opt => {
      map.set(opt.value, opt.label);
    });
    return map;
  }, [options]);

  // Memoized Lookup-Maps für Performance
  const lookupMaps = useMemo(() => ({
    users: createLookupMap('users'),
    organisations: createLookupMap('organisations'),
    roles: createLookupMap('roles'),
    contracts: createLookupMap('contracts'),
    documents: createLookupMap('documents'),
    positions: createLookupMap('positions'),
  }), [createLookupMap]);

  /**
   * Schnelle Label-Auflösung via Lookup-Map.
   */
  const getLabelFast = useCallback((entity: TrusteeOptionEntity, value: string | null | undefined): string => {
    if (value === null || value === undefined || value === '') {
      return '-';
    }
    return lookupMaps[entity].get(value) || value;
  }, [lookupMaps]);

  // Auto-Load beim Mount
  useEffect(() => {
    if (autoLoad.length > 0) {
      // Nur laden wenn instanceId verfügbar (oder nur 'users' geladen werden soll)
      const needsInstance = autoLoad.some(e => e !== 'users');
      if (!needsInstance || instanceId) {
        loadOptions(autoLoad);
      }
    }
  }, [instanceId, autoLoad.join(',')]); // autoLoad als String-Join für Dependency-Vergleich

  return {
    // State
    options,
    loading,
    error,
    
    // Actions
    loadOptions,
    loadContractsForOrganisation,
    
    // Getters
    getLabel,
    getLabelFast,
    getOptions,
    isLoaded,
    createLookupMap,
    
    // Context
    instanceId,
  };
}

// ============================================================================
// CONVENIENCE EXPORTS
// ============================================================================

/**
 * Hook speziell für TrusteeAccessView.
 * Lädt automatisch users, organisations und roles.
 */
export function useTrusteeAccessOptions() {
  return useTrusteeOptions(['users', 'organisations', 'roles']);
}

/**
 * Hook speziell für Views mit Organisation+Contract Dropdowns.
 * Lädt automatisch organisations und contracts.
 */
export function useTrusteeOrgContractOptions() {
  return useTrusteeOptions(['organisations', 'contracts']);
}

export default useTrusteeOptions;
