import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { tripsApi } from '@/db/api';
import { useToast } from '@/hooks/use-toast';
import { Trip, TripDataRaw } from '@/types/trip-ui';

// Simple in-memory cache
const tripCache: Record<string, Trip> = {};

interface TripDataContextState {
  trip: Trip | null;
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
}

interface TripDataContextActions {
  loadTrip: (id: string, isSilent?: boolean) => Promise<void>;
  updateTrip: (updates: Partial<Trip>) => Promise<void>;
  deleteTrip: () => Promise<void>;
}

const TripDataStateContext = createContext<TripDataContextState | undefined>(undefined);
const TripDataActionsContext = createContext<TripDataContextActions | undefined>(undefined);

/**
 * TripDataProvider - Seyahat verilerini yöneten ana sağlayıcı.
 * Uygulamanın üst seviyelerinde (örn. TripProviders.tsx) sarmalanmalıdır.
 */
export const TripDataProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [state, setState] = useState<TripDataContextState>({
    trip: null,
    isLoading: false,
    isError: false,
    error: null,
  });
  
  const { toast } = useToast();
  const previousTrip = useRef<Trip | null>(null);

  const transformTripData = useCallback((data: TripDataRaw): Trip => {
    const fallbackDate = new Date().toISOString();
    return {
      id: data.id,
      title: data.title || 'İsimsiz Seyahat',
      destination: data.destination || 'Hedef Belirtilmedi',
      startDate: data.start_date || fallbackDate,
      endDate: data.end_date || fallbackDate,
      start_date: data.start_date || fallbackDate,
      end_date: data.end_date || fallbackDate,
      travelers: data.number_of_travelers || 2,
      number_of_travelers: data.number_of_travelers || 2,
      coverImage: data.cover_image || 'https://images.unsplash.com/photo-1469854523086-cc02fe5d8800?q=80&w=2021&auto=format&fit=crop',
      has_balloon: data.has_balloon,
      balloon_day_id: data.balloon_day_id,
      start_lat: data.start_lat,
      start_lng: data.start_lng,
      start_location_name: data.start_location_name,
      start_location_type: data.start_location_type,
      interests: data.interests || [],
      created_at: data.created_at || fallbackDate,
      updated_at: data.updated_at || fallbackDate,
      days: (data.trip_days || []).map((day) => ({
        id: day.id,
        dayNumber: day.day_number,
        date: day.date || fallbackDate.split('T')[0],
        dayName: new Date(day.date || fallbackDate).toLocaleDateString('tr-TR', { weekday: 'long' }),
        places: (day.trip_places || []).map((tp) => ({
          id: tp.place_id,
          tripPlaceId: tp.id,
          name: tp.place?.name || 'Bilinmeyen Yer',
          type: tp.place?.type || 'poi',
          duration: tp.place?.duration || '1-2 saat',
          img: tp.place?.image_url,
          position: {
            lat: tp.place?.latitude || 0,
            lng: tp.place?.longitude || 0,
          },
          rating: tp.place?.rating,
          description: tp.place?.description,
          timeOfDay: tp.time_of_day,
          notes: tp.notes || '',
          order_index: tp.order_index,
        })).sort((a, b) => (a.order_index || 0) - (b.order_index || 0)),
      })).sort((a, b) => a.dayNumber - b.dayNumber),
    };
  }, []);

  const loadTrip = useCallback(async (id: string, isSilent = false) => {
    if (!id) return;

    try {
      if (!isSilent) setState(prev => ({ ...prev, isLoading: true, isError: false, error: null }));
      
      const data = await tripsApi.getTripById(id);
      if (!data) throw new Error('Seyahat bulunamadı.');

      const transformedTrip = transformTripData(data);
      tripCache[`trip_${id}`] = transformedTrip;
      
      setState({
        trip: transformedTrip,
        isLoading: false,
        isError: false,
        error: null,
      });
    } catch (err) {
      setState(prev => ({ ...prev, isLoading: false, isError: true, error: err instanceof Error ? err : new Error('Bilinmeyen hata') }));
      if (!isSilent) {
        toast({
          title: 'Hata',
          description: err instanceof Error ? err.message : 'Seyahat yüklenirken bir hata oluştu.',
          variant: 'destructive',
        });
      }
    }
  }, [transformTripData, toast]);

  const updateTrip = useCallback(async (updates: Partial<Trip>) => {
    const currentTrip = state.trip;
    if (!currentTrip) return;

    previousTrip.current = { ...currentTrip };
    const updatedTrip = { ...currentTrip, ...updates };

    // Optimistic Update
    setState(prev => ({ ...prev, trip: updatedTrip }));
    tripCache[`trip_${currentTrip.id}`] = updatedTrip;

    try {
      await tripsApi.update(currentTrip.id, updates);
      toast({
        title: 'Başarılı',
        description: 'Seyahat planı güncellendi.',
      });
    } catch (err) {
      // Rollback
      if (previousTrip.current) {
        setState(prev => ({ ...prev, trip: previousTrip.current }));
        tripCache[`trip_${currentTrip.id}`] = previousTrip.current;
      }
      toast({
        title: 'Güncelleme Hatası',
        description: err instanceof Error ? err.message : 'Değişiklikler geri alındı.',
        variant: 'destructive',
      });
    }
  }, [state.trip, toast]);

  const deleteTrip = useCallback(async () => {
    const currentTrip = state.trip;
    if (!currentTrip) return;

    try {
      await tripsApi.delete(currentTrip.id);
      delete tripCache[`trip_${currentTrip.id}`];
      setState({ trip: null, isLoading: false, isError: false, error: null });
      
      toast({
        title: 'Başarılı',
        description: 'Seyahat başarıyla silindi.',
      });
    } catch (err) {
      toast({
        title: 'Silme Hatası',
        description: err instanceof Error ? err.message : 'Seyahat silinemedi.',
        variant: 'destructive',
      });
    }
  }, [state.trip, toast]);

  const actions = React.useMemo(() => ({ loadTrip, updateTrip, deleteTrip }), [loadTrip, updateTrip, deleteTrip]);

  return (
    <TripDataStateContext.Provider value={state}>
      <TripDataActionsContext.Provider value={actions}>
        {children}
      </TripDataActionsContext.Provider>
    </TripDataStateContext.Provider>
  );
};

/**
 * useTripData - Ana Hook (Geriye tüm metodları ve durumu döner)
 */
export const useTripData = (tripId?: string) => {
  const state = useContext(TripDataStateContext);
  const actions = useContext(TripDataActionsContext);

  if (!state || !actions) {
    throw new Error('useTripData, TripDataProvider içerisinde kullanılmalıdır.');
  }

  // Otomatik yükleme (Automatic refetch on trip ID change)
  useEffect(() => {
    if (tripId) {
      const cached = tripCache[`trip_${tripId}`];
      if (cached && state.trip?.id !== tripId) {
        // Cache'te varsa hemen göster ve arka planda güncelle (Stale-while-revalidate)
        actions.loadTrip(tripId, true);
      } else if (!cached || state.trip?.id !== tripId) {
        actions.loadTrip(tripId);
      }
    }
  }, [tripId, actions, state.trip?.id]);

  return {
    ...state,
    ...actions,
    useTrip: () => state.trip,
    useLoadTrip: actions.loadTrip,
    useUpdateTrip: actions.updateTrip,
    useDeleteTrip: actions.deleteTrip,
    useTripIsLoading: state.isLoading,
    useTripIsError: state.isError,
  };
};

/**
 * Bağımsız Hooklar (Requirements'da belirtilen METHODS listesi için)
 */
export const useTrip = () => {
  const context = useContext(TripDataStateContext);
  if (!context) throw new Error('useTrip, TripDataProvider içerisinde kullanılmalıdır.');
  return context.trip;
};

export const useTripIsLoading = () => {
  const context = useContext(TripDataStateContext);
  if (!context) throw new Error('useTripIsLoading, TripDataProvider içerisinde kullanılmalıdır.');
  return context.isLoading;
};

export const useTripIsError = () => {
  const context = useContext(TripDataStateContext);
  if (!context) throw new Error('useTripIsError, TripDataProvider içerisinde kullanılmalıdır.');
  return context.isError;
};

export const useLoadTrip = () => {
  const actions = useContext(TripDataActionsContext);
  if (!actions) throw new Error('useLoadTrip, TripDataProvider içerisinde kullanılmalıdır.');
  return actions.loadTrip;
};

export const useUpdateTrip = () => {
  const actions = useContext(TripDataActionsContext);
  if (!actions) throw new Error('useUpdateTrip, TripDataProvider içerisinde kullanılmalıdır.');
  return actions.updateTrip;
};

export const useDeleteTrip = () => {
  const actions = useContext(TripDataActionsContext);
  if (!actions) throw new Error('useDeleteTrip, TripDataProvider içerisinde kullanılmalıdır.');
  return actions.deleteTrip;
};
