/**
 * useRecommendations Hook
 *
 * Subscribe to AI-generated recommendations with filtering.
 * Subscribes to tenant-wide recommendations channel via SSE.
 *
 * Examples:
 *   const { recommendations } = useRecommendations(); // All recommendations
 *   const { recommendations } = useRecommendations({ domains: ['demand'], minConfidence: 0.8 });
 *   const { recommendations } = useRecommendations({ includeDismissed: false });
 */

import { useState, useEffect, useMemo, useCallback } from 'react';
import { useSSEEvents } from './useSSE';
import type {
  Recommendation,
  EventDomain,
  UseRecommendationsConfig,
} from '../api/types/events';
import { isRecommendation } from '../api/types/events';

interface UseRecommendationsReturn {
  recommendations: Recommendation[];
  activeRecommendations: Recommendation[];
  highConfidenceRecommendations: Recommendation[];
  isLoading: boolean;
  dismiss: (recommendationId: string) => void;
  clearRecommendations: () => void;
}

export function useRecommendations(config: UseRecommendationsConfig = {}): UseRecommendationsReturn {
  const {
    domains,
    includeDismissed = false,
    minConfidence = 0.0,
  } = config;

  // Recommendations are tenant-wide, not domain-specific
  // But we can filter by domain after receiving
  const channels = useMemo(() => ['recommendations'], []);

  // Subscribe to SSE with channel filter
  const { events, isConnected } = useSSEEvents({ channels });

  // Filter events to recommendations only
  const [recommendations, setRecommendations] = useState<Recommendation[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Filter and process incoming events
    const recommendationEvents = events.filter(isRecommendation);

    // Apply filters
    let filtered = recommendationEvents;

    // Filter by domain
    if (domains && domains.length > 0) {
      filtered = filtered.filter(rec => domains.includes(rec.event_domain));
    }

    // Filter by confidence
    if (minConfidence > 0) {
      filtered = filtered.filter(rec => {
        const confidence = rec.confidence_score ?? 1.0;
        return confidence >= minConfidence;
      });
    }

    // Filter dismissed recommendations
    if (!includeDismissed) {
      filtered = filtered.filter(rec => !rec.dismissed_at);
    }

    // Sort by confidence (highest first), then by timestamp (newest first)
    filtered.sort((a, b) => {
      const confidenceA = a.confidence_score ?? 0.5;
      const confidenceB = b.confidence_score ?? 0.5;
      const confidenceDiff = confidenceB - confidenceA;
      if (Math.abs(confidenceDiff) > 0.01) return confidenceDiff;

      const timeA = new Date(a.created_at).getTime();
      const timeB = new Date(b.created_at).getTime();
      return timeB - timeA;
    });

    setRecommendations(filtered);
    setIsLoading(false);
  }, [events, domains, minConfidence, includeDismissed]);

  // Computed values
  const activeRecommendations = useMemo(() => {
    return recommendations.filter(rec => !rec.dismissed_at);
  }, [recommendations]);

  const highConfidenceRecommendations = useMemo(() => {
    return recommendations.filter(rec => (rec.confidence_score ?? 0.5) >= 0.8);
  }, [recommendations]);

  // Actions
  const dismiss = useCallback((recommendationId: string) => {
    setRecommendations(prev =>
      prev.map(rec =>
        rec.id === recommendationId
          ? { ...rec, dismissed_at: new Date().toISOString() }
          : rec
      )
    );
    // TODO: Send dismissal to backend
  }, []);

  const clearRecommendations = useCallback(() => {
    setRecommendations([]);
  }, []);

  return {
    recommendations,
    activeRecommendations,
    highConfidenceRecommendations,
    isLoading: isLoading || !isConnected,
    dismiss,
    clearRecommendations,
  };
}

/**
 * useRecommendationsByDomain Hook
 *
 * Get recommendations grouped by domain.
 */
export function useRecommendationsByDomain(config: UseRecommendationsConfig = {}) {
  const { recommendations, ...rest } = useRecommendations(config);

  const recommendationsByDomain = useMemo(() => {
    const grouped: Partial<Record<EventDomain, Recommendation[]>> = {};

    recommendations.forEach(rec => {
      if (!grouped[rec.event_domain]) {
        grouped[rec.event_domain] = [];
      }
      grouped[rec.event_domain]!.push(rec);
    });

    return grouped;
  }, [recommendations]);

  return {
    recommendations,
    recommendationsByDomain,
    ...rest,
  };
}

/**
 * useRecommendationsByType Hook
 *
 * Get recommendations grouped by recommendation type.
 */
export function useRecommendationsByType(config: UseRecommendationsConfig = {}) {
  const { recommendations, ...rest } = useRecommendations(config);

  const recommendationsByType = useMemo(() => {
    const grouped: Partial<Record<string, Recommendation[]>> = {};

    recommendations.forEach(rec => {
      if (!grouped[rec.recommendation_type]) {
        grouped[rec.recommendation_type] = [];
      }
      grouped[rec.recommendation_type]!.push(rec);
    });

    return grouped;
  }, [recommendations]);

  return {
    recommendations,
    recommendationsByType,
    ...rest,
  };
}

/**
 * useDemandRecommendations Hook
 *
 * Convenience hook for demand/forecasting recommendations.
 */
export function useDemandRecommendations() {
  return useRecommendations({
    domains: ['demand'],
    includeDismissed: false,
  });
}

/**
 * useInventoryOptimizationRecommendations Hook
 *
 * Convenience hook for inventory optimization recommendations.
 */
export function useInventoryOptimizationRecommendations() {
  return useRecommendations({
    domains: ['inventory'],
    includeDismissed: false,
    minConfidence: 0.7,
  });
}

/**
 * useCostReductionRecommendations Hook
 *
 * Convenience hook for cost reduction recommendations.
 */
export function useCostReductionRecommendations() {
  return useRecommendations({
    domains: ['supply_chain'],
    includeDismissed: false,
    minConfidence: 0.75,
  });
}

/**
 * useHighConfidenceRecommendations Hook
 *
 * Convenience hook for high-confidence recommendations (>= 80%).
 */
export function useHighConfidenceRecommendations(domains?: EventDomain[]) {
  return useRecommendations({
    domains,
    includeDismissed: false,
    minConfidence: 0.8,
  });
}
