'use client';

import { useState, useEffect, useCallback, useMemo } from 'react';
import { TimeEntry } from '@/lib/types/database';
import { 
  TimelineEvent, 
  AnalyticsInsight, 
  LLMAnalysisResponse,
  AggregateAnalysis
} from '@/lib/types/analytics';
import { 
  analyticsIntegration,
  EnrichedTimeEntry,
  EnrichmentOptions 
} from '@/lib/services/analytics-integration';
import { analyticsEngine } from '@/lib/services/analytics-engine';
import { llmAnalyzer } from '@/lib/services/llm-analyzer';

export interface TimeEntriesFilter {
  startDate?: string;
  endDate?: string;
  resourceIds?: number[];
  ticketIds?: number[];
  taskIds?: number[];
  projectIds?: number[];
  companyIds?: number[];
  minHours?: number;
  maxHours?: number;
  billable?: boolean;
  approved?: boolean;
  search?: string;
  limit?: number;
  offset?: number;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
}

export interface UseTimeEntriesOptions {
  autoFetch?: boolean;
  enableAnalysis?: boolean;
  enableEnrichment?: boolean;
  enrichmentOptions?: EnrichmentOptions;
  cacheKey?: string;
  cacheTimeout?: number; // milliseconds
}

export interface TimeEntriesState {
  timeEntries: TimeEntry[];
  enrichedTimeEntries: EnrichedTimeEntry[];
  timelineEvents: TimelineEvent[];
  analysis: AggregateAnalysis | null;
  insights: AnalyticsInsight[];
  llmAnalysis: LLMAnalysisResponse | null;
  loading: boolean;
  error: string | null;
  pagination: {
    total: number;
    limit: number;
    offset: number;
    hasMore: boolean;
  };
}

export function useTimeEntries(
  initialFilter: TimeEntriesFilter = {},
  options: UseTimeEntriesOptions = {}
) {
  const {
    autoFetch = true,
    enableAnalysis = true,
    enableEnrichment = true,
    enrichmentOptions = {
      includeResourceInfo: true,
      includeTicketInfo: true,
      includeProjectInfo: true,
      includeCompanyInfo: true,
      includeAnalysis: true,
    },
    cacheKey = 'time-entries',
    cacheTimeout = 5 * 60 * 1000, // 5 minutes
  } = options;

  const [filter, setFilter] = useState<TimeEntriesFilter>(initialFilter);
  const [state, setState] = useState<TimeEntriesState>({
    timeEntries: [],
    enrichedTimeEntries: [],
    timelineEvents: [],
    analysis: null,
    insights: [],
    llmAnalysis: null,
    loading: false,
    error: null,
    pagination: {
      total: 0,
      limit: 100,
      offset: 0,
      hasMore: false,
    },
  });

  // Simple cache implementation
  const cache = useMemo(() => new Map<string, { data: any; timestamp: number }>(), []);

  const getCacheKey = useCallback((filter: TimeEntriesFilter) => {
    return `${cacheKey}-${JSON.stringify(filter)}`;
  }, [cacheKey]);

  const getCachedData = useCallback((key: string) => {
    const cached = cache.get(key);
    if (cached && Date.now() - cached.timestamp < cacheTimeout) {
      return cached.data;
    }
    cache.delete(key);
    return null;
  }, [cache, cacheTimeout]);

  const setCachedData = useCallback((key: string, data: any) => {
    cache.set(key, { data, timestamp: Date.now() });
  }, [cache]);

  // Fetch time entries from API
  const fetchTimeEntries = useCallback(async (filterOverrides: Partial<TimeEntriesFilter> = {}) => {
    const currentFilter = { ...filter, ...filterOverrides };
    const cacheKey = getCacheKey(currentFilter);
    
    // Check cache first
    const cached = getCachedData(cacheKey);
    if (cached) {
      setState(cached);
      return cached;
    }

    setState(prev => ({ ...prev, loading: true, error: null }));

    try {
      // Build query string
      const params = new URLSearchParams();
      
      if (currentFilter.startDate) params.append('start_date', currentFilter.startDate);
      if (currentFilter.endDate) params.append('end_date', currentFilter.endDate);
      if (currentFilter.minHours) params.append('min_hours', currentFilter.minHours.toString());
      if (currentFilter.maxHours) params.append('max_hours', currentFilter.maxHours.toString());
      if (currentFilter.billable !== undefined) params.append('billable', currentFilter.billable.toString());
      if (currentFilter.approved !== undefined) params.append('approved', currentFilter.approved.toString());
      if (currentFilter.search) params.append('search', currentFilter.search);
      if (currentFilter.limit) params.append('limit', currentFilter.limit.toString());
      if (currentFilter.offset) params.append('offset', currentFilter.offset.toString());
      if (currentFilter.sortBy) params.append('sort_by', currentFilter.sortBy);
      if (currentFilter.sortOrder) params.append('sort_order', currentFilter.sortOrder);
      
      if (currentFilter.resourceIds?.length) {
        params.append('resource_ids', currentFilter.resourceIds.join(','));
      }
      if (currentFilter.ticketIds?.length) {
        params.append('ticket_ids', currentFilter.ticketIds.join(','));
      }
      if (currentFilter.taskIds?.length) {
        params.append('task_ids', currentFilter.taskIds.join(','));
      }
      if (currentFilter.projectIds?.length) {
        params.append('project_ids', currentFilter.projectIds.join(','));
      }
      if (currentFilter.companyIds?.length) {
        params.append('company_ids', currentFilter.companyIds.join(','));
      }

      const response = await fetch(`/api/data/time-entries?${params}`);
      
      if (!response.ok) {
        throw new Error(`Failed to fetch time entries: ${response.statusText}`);
      }

      const data = await response.json();
      const timeEntries: TimeEntry[] = data.timeEntries || [];
      
      let enrichedTimeEntries: EnrichedTimeEntry[] = [];
      let timelineEvents: TimelineEvent[] = [];
      let analysis: AggregateAnalysis | null = null;
      let insights: AnalyticsInsight[] = [];

      // Enrich data if enabled
      if (enableEnrichment && timeEntries.length > 0) {
        enrichedTimeEntries = await analyticsIntegration.enrichTimeEntries(
          timeEntries,
          enrichmentOptions
        );
        
        timelineEvents = await analyticsIntegration.generateTimelineEvents(
          timeEntries,
          enrichmentOptions
        );
      }

      // Generate analysis if enabled
      if (enableAnalysis && timeEntries.length > 0) {
        const analysisResult = await analyticsIntegration.generateComprehensiveAnalysis(
          timeEntries,
          enrichmentOptions
        );
        
        analysis = analysisResult.analysis;
        insights = analysisResult.entityInsights;
      }

      const newState: TimeEntriesState = {
        timeEntries,
        enrichedTimeEntries,
        timelineEvents,
        analysis,
        insights,
        llmAnalysis: null,
        loading: false,
        error: null,
        pagination: data.pagination || {
          total: timeEntries.length,
          limit: currentFilter.limit || 100,
          offset: currentFilter.offset || 0,
          hasMore: false,
        },
      };

      setState(newState);
      setCachedData(cacheKey, newState);
      
      return newState;

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      setState(prev => ({
        ...prev,
        loading: false,
        error: errorMessage,
      }));
      throw error;
    }
  }, [filter, enableEnrichment, enableAnalysis, enrichmentOptions, getCacheKey, getCachedData, setCachedData]);

  // Generate LLM analysis
  const generateLLMAnalysis = useCallback(async (
    analysisType: 'productivity' | 'quality' | 'patterns' | 'anomalies' | 'comprehensive' = 'comprehensive'
  ) => {
    if (state.timeEntries.length === 0) {
      return null;
    }

    setState(prev => ({ ...prev, loading: true, error: null }));

    try {
      const llmAnalysis = await analyticsIntegration.generateLLMAnalysis(
        state.timeEntries,
        analysisType,
        enrichmentOptions
      );

      setState(prev => ({
        ...prev,
        llmAnalysis,
        loading: false,
      }));

      return llmAnalysis;

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      setState(prev => ({
        ...prev,
        loading: false,
        error: errorMessage,
      }));
      throw error;
    }
  }, [state.timeEntries, enrichmentOptions]);

  // Refresh data
  const refresh = useCallback(() => {
    return fetchTimeEntries();
  }, [fetchTimeEntries]);

  // Update filter
  const updateFilter = useCallback((newFilter: Partial<TimeEntriesFilter>) => {
    setFilter(prev => ({ ...prev, ...newFilter }));
  }, []);

  // Reset filter
  const resetFilter = useCallback(() => {
    setFilter(initialFilter);
  }, [initialFilter]);

  // Load more data (pagination)
  const loadMore = useCallback(() => {
    if (!state.pagination.hasMore) return;
    
    return fetchTimeEntries({
      offset: state.pagination.offset + state.pagination.limit,
    });
  }, [fetchTimeEntries, state.pagination]);

  // Export data
  const exportData = useCallback(async (format: 'csv' | 'excel' | 'pdf' | 'json' = 'csv') => {
    try {
      const params = new URLSearchParams({ format });
      
      // Apply current filter to export
      Object.entries(filter).forEach(([key, value]) => {
        if (value !== undefined && value !== null) {
          if (Array.isArray(value)) {
            params.append(key, value.join(','));
          } else {
            params.append(key, String(value));
          }
        }
      });

      const response = await fetch(`/api/data/time-entries/export?${params}`);
      
      if (!response.ok) {
        throw new Error(`Failed to export data: ${response.statusText}`);
      }

      // Get filename from response headers or create default
      const contentDisposition = response.headers.get('content-disposition');
      const filename = contentDisposition 
        ? contentDisposition.split('filename=')[1]?.replace(/"/g, '') 
        : `time-entries-${new Date().toISOString().split('T')[0]}.${format}`;

      // Download file
      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      setState(prev => ({ ...prev, error: errorMessage }));
      throw error;
    }
  }, [filter]);

  // Auto-fetch on filter change
  useEffect(() => {
    if (autoFetch) {
      fetchTimeEntries();
    }
  }, [filter, autoFetch, fetchTimeEntries]);

  // Memoized computed values
  const computed = useMemo(() => ({
    totalEntries: state.timeEntries.length,
    totalHours: state.timeEntries.reduce((sum, entry) => sum + entry.hours_worked, 0),
    averageHoursPerEntry: state.timeEntries.length > 0 
      ? state.timeEntries.reduce((sum, entry) => sum + entry.hours_worked, 0) / state.timeEntries.length 
      : 0,
    billableEntries: state.timeEntries.filter(entry => entry.billable).length,
    approvedEntries: state.timeEntries.filter(entry => entry.approved).length,
    averageScore: state.analysis?.scores.overall || 0,
  }), [state.timeEntries, state.analysis]);

  return {
    // State
    ...state,
    
    // Computed values
    computed,
    
    // Actions
    fetchTimeEntries,
    generateLLMAnalysis,
    refresh,
    updateFilter,
    resetFilter,
    loadMore,
    exportData,
    
    // Filter
    filter,
    setFilter,
  };
}

// Hook for individual time entry analysis
export function useTimeEntryAnalysis(timeEntryId: number) {
  const [timeEntry, setTimeEntry] = useState<TimeEntry | null>(null);
  const [analysis, setAnalysis] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const fetchTimeEntry = useCallback(async () => {
    setLoading(true);
    setError(null);

    try {
      const response = await fetch(`/api/data/time-entries/${timeEntryId}`);
      
      if (!response.ok) {
        throw new Error(`Failed to fetch time entry: ${response.statusText}`);
      }

      const data = await response.json();
      setTimeEntry(data.timeEntry);
      
      // Generate analysis
      if (data.timeEntry) {
        const entryAnalysis = analyticsEngine.analyzeTimeEntry(data.timeEntry);
        setAnalysis(entryAnalysis);
      }

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      setError(errorMessage);
    } finally {
      setLoading(false);
    }
  }, [timeEntryId]);

  useEffect(() => {
    if (timeEntryId) {
      fetchTimeEntry();
    }
  }, [timeEntryId, fetchTimeEntry]);

  return {
    timeEntry,
    analysis,
    loading,
    error,
    refresh: fetchTimeEntry,
  };
}

// Hook for real-time analytics updates
export function useRealTimeAnalytics(refreshInterval: number = 60000) { // 1 minute default
  const [lastUpdate, setLastUpdate] = useState<Date>(new Date());
  const [isConnected, setIsConnected] = useState(false);
  
  const timeEntriesHook = useTimeEntries();

  // Set up real-time updates
  useEffect(() => {
    const interval = setInterval(() => {
      timeEntriesHook.refresh();
      setLastUpdate(new Date());
    }, refreshInterval);

    setIsConnected(true);

    return () => {
      clearInterval(interval);
      setIsConnected(false);
    };
  }, [refreshInterval, timeEntriesHook]);

  return {
    ...timeEntriesHook,
    lastUpdate,
    isConnected,
  };
}
