/**
 * Feature Store
 * 
 * Verwaltet alle Mandate → Features → Instanzen → Permissions
 * Ein User gehört keinem Mandanten direkt an, sondern hat Zugriff auf Feature-Instanzen.
 */

import React, { createContext, useContext, useState, useCallback, useRef, ReactNode } from 'react';
import type {
  Mandate,
  MandateFeature,
  FeatureInstance,
  FeaturesMyResponse,
} from '../types/mandate';

// =============================================================================
// STORE STATE
// =============================================================================

interface FeatureState {
  mandates: Mandate[];
  loading: boolean;
  error: string | null;
  initialized: boolean;
}

interface FeatureActions {
  // Laden
  loadFeatures: () => Promise<void>;
  setFeatures: (response: FeaturesMyResponse) => void;
  
  // Getters
  getMandateById: (mandateId: string) => Mandate | undefined;
  getFeatureByCode: (mandateId: string, featureCode: string) => MandateFeature | undefined;
  getInstanceById: (instanceId: string) => FeatureInstance | undefined;
  getInstancesByFeature: (mandateId: string, featureCode: string) => FeatureInstance[];
  
  // Alle Instanzen flach
  getAllInstances: () => FeatureInstance[];
  
  // Prüfungen
  hasAnyInstance: () => boolean;
  
  // Reset
  reset: () => void;
}

type FeatureStore = FeatureState & FeatureActions;

// =============================================================================
// INITIAL STATE
// =============================================================================

const initialState: FeatureState = {
  mandates: [],
  loading: false,
  error: null,
  initialized: false,
};

// =============================================================================
// CONTEXT
// =============================================================================

const FeatureContext = createContext<FeatureStore | undefined>(undefined);

// =============================================================================
// PROVIDER
// =============================================================================

interface FeatureProviderProps {
  children: ReactNode;
}

export const FeatureProvider: React.FC<FeatureProviderProps> = ({ children }) => {
  const [state, setState] = useState<FeatureState>(initialState);
  
  // Cache für schnellen Zugriff auf Instanzen
  const instanceCacheRef = useRef<Map<string, FeatureInstance>>(new Map());

  /**
   * Lädt alle Features vom Backend
   */
  const loadFeatures = useCallback(async () => {
    setState(prev => ({ ...prev, loading: true, error: null }));
    
    try {
      // Import dynamisch um zirkuläre Abhängigkeiten zu vermeiden
      const { fetchMyFeatures } = await import('../api/featuresApi');
      const response = await fetchMyFeatures();
      
      // Cache aufbauen
      const cache = new Map<string, FeatureInstance>();
      response.mandates.forEach(mandate => {
        mandate.features.forEach(feature => {
          feature.instances.forEach(instance => {
            cache.set(instance.id, instance);
          });
        });
      });
      instanceCacheRef.current = cache;
      
      setState({
        mandates: response.mandates,
        loading: false,
        error: null,
        initialized: true,
      });
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to load features';
      console.error('FeatureStore: Error loading features:', err);
      setState(prev => ({
        ...prev,
        loading: false,
        error: errorMessage,
        initialized: true,
      }));
    }
  }, []);

  /**
   * Setzt Features direkt (z.B. nach Login)
   */
  const setFeatures = useCallback((response: FeaturesMyResponse) => {
    // Cache aufbauen
    const cache = new Map<string, FeatureInstance>();
    response.mandates.forEach(mandate => {
      mandate.features.forEach(feature => {
        feature.instances.forEach(instance => {
          cache.set(instance.id, instance);
        });
      });
    });
    instanceCacheRef.current = cache;
    
    setState({
      mandates: response.mandates,
      loading: false,
      error: null,
      initialized: true,
    });
  }, []);

  /**
   * Holt einen Mandanten per ID
   */
  const getMandateById = useCallback((mandateId: string): Mandate | undefined => {
    return state.mandates.find(m => m.id === mandateId);
  }, [state.mandates]);

  /**
   * Holt ein Feature per Mandate-ID und Feature-Code
   */
  const getFeatureByCode = useCallback((mandateId: string, featureCode: string): MandateFeature | undefined => {
    const mandate = state.mandates.find(m => m.id === mandateId);
    return mandate?.features.find(f => f.code === featureCode);
  }, [state.mandates]);

  /**
   * Holt eine Instanz per ID (schneller Cache-Zugriff)
   */
  const getInstanceById = useCallback((instanceId: string): FeatureInstance | undefined => {
    return instanceCacheRef.current.get(instanceId);
  }, []);

  /**
   * Holt alle Instanzen für ein Feature in einem Mandanten
   */
  const getInstancesByFeature = useCallback((mandateId: string, featureCode: string): FeatureInstance[] => {
    const feature = getFeatureByCode(mandateId, featureCode);
    return feature?.instances || [];
  }, [getFeatureByCode]);

  /**
   * Holt alle Instanzen flach
   */
  const getAllInstances = useCallback((): FeatureInstance[] => {
    return Array.from(instanceCacheRef.current.values());
  }, []);

  /**
   * Prüft ob der User mindestens eine Instanz hat
   */
  const hasAnyInstance = useCallback((): boolean => {
    return instanceCacheRef.current.size > 0;
  }, []);

  /**
   * Reset (z.B. bei Logout)
   */
  const reset = useCallback(() => {
    instanceCacheRef.current.clear();
    setState(initialState);
  }, []);

  // Store zusammenbauen
  const store: FeatureStore = {
    ...state,
    loadFeatures,
    setFeatures,
    getMandateById,
    getFeatureByCode,
    getInstanceById,
    getInstancesByFeature,
    getAllInstances,
    hasAnyInstance,
    reset,
  };

  return (
    <FeatureContext.Provider value={store}>
      {children}
    </FeatureContext.Provider>
  );
};

// =============================================================================
// HOOKS
// =============================================================================

/**
 * Hook für Zugriff auf den Feature Store
 */
export function useFeatureStore(): FeatureStore {
  const context = useContext(FeatureContext);
  if (!context) {
    throw new Error('useFeatureStore must be used within a FeatureProvider');
  }
  return context;
}

/**
 * Hook für alle Mandate
 */
export function useMandates(): Mandate[] {
  const store = useFeatureStore();
  return store.mandates;
}

/**
 * Hook für einen spezifischen Mandanten
 */
export function useMandateById(mandateId: string | undefined): Mandate | undefined {
  const store = useFeatureStore();
  if (!mandateId) return undefined;
  return store.getMandateById(mandateId);
}

/**
 * Hook für eine spezifische Instanz
 */
export function useInstance(instanceId: string | undefined): FeatureInstance | undefined {
  const store = useFeatureStore();
  if (!instanceId) return undefined;
  return store.getInstanceById(instanceId);
}

/**
 * Hook für Loading-State
 */
export function useFeaturesLoading(): boolean {
  const store = useFeatureStore();
  return store.loading;
}

/**
 * Hook für Error-State
 */
export function useFeaturesError(): string | null {
  const store = useFeatureStore();
  return store.error;
}

/**
 * Hook für Initialized-State
 */
export function useFeaturesInitialized(): boolean {
  const store = useFeatureStore();
  return store.initialized;
}
