import { create } from 'zustand';
import { placesApi, tripPlacesApi, tripsApi } from '@/db/api';
import { Trip, TripPlace, MapMarker, TimelineBlock } from '@/types/trip-ui';
import { assignTimeBlocks, type TimeBlock } from '@/lib/time-blocks';
import { transformTripData } from '@/lib/trip-transform';

interface TripState {
  // Data State
  trip: Trip | null;
  loading: boolean;
  error: Error | null;
  
  // UI State
  hoveredPlaceId: string | null;
  selectedPlaceId: string | null;
  activeTab: 'timeline' | 'map';
  isAddPlaceOpen: boolean;
  highlightedPlaceId: string | null;
  newlyAddedPlaceId: string | null;
  activeDayId: string | null;

  // Actions
  loadTrip: (tripId: string) => Promise<void>;
  updateTrip: (updates: Partial<Trip>) => Promise<void>;
  deleteTrip: (tripId: string) => Promise<void>;
  addPlaceToDay: (placeId: string, dayId: string, options?: { time_block?: string; notes?: string }) => Promise<void>;
  removePlaceFromDay: (tripPlaceId: string) => Promise<void>;
  
  // UI Actions
  setHoveredPlaceId: (id: string | null) => void;
  setSelectedPlaceId: (id: string | null) => void;
  setActiveTab: (tab: 'timeline' | 'map') => void;
  setIsAddPlaceOpen: (open: boolean) => void;
  setHighlightedPlaceId: (id: string | null) => void;
  setNewlyAddedPlaceId: (id: string | null) => void;
  setActiveDayId: (dayId: string | null) => void;
  
  // Logic Actions
  reorderPlaces: (dayId: string, places: TripPlace[]) => Promise<void>;
}

export const useTripStore = create<TripState>((set, get) => ({
  // Initial State
  trip: null,
  loading: false,
  error: null,
  hoveredPlaceId: null,
  selectedPlaceId: null,
  activeTab: 'timeline',
  isAddPlaceOpen: false,
  highlightedPlaceId: null,
  newlyAddedPlaceId: null,
  activeDayId: null,

  // Actions
  loadTrip: async (tripId) => {
    try {
      set({ loading: true, error: null });
      const tripData = await tripsApi.getTripById(tripId);
      
      if (tripData) {
        const transformedTrip = transformTripData(tripData);
        
        set({ trip: transformedTrip });
        
        // Restore active day
        const storedDayId = localStorage.getItem(`trip_active_day_${tripId}`);
        const isStoredValid = transformedTrip.days.some(day => day.id === storedDayId);
        
        if (storedDayId && isStoredValid) {
          set({ activeDayId: storedDayId });
        } else if (transformedTrip.days.length > 0) {
          set({ activeDayId: transformedTrip.days[0].id });
        }
      } else {
        throw new Error('Trip not found');
      }
    } catch (err: any) {
      set({ error: err });
      console.error('loadTrip error:', err);
    } finally {
      set({ loading: false });
    }
  },

  updateTrip: async (updates) => {
    const { trip } = get();
    if (!trip) return;
    try {
      await tripsApi.update(trip.id, updates);
      set((state) => ({
        trip: state.trip ? { ...state.trip, ...updates } : null
      }));
    } catch (err: any) {
      console.error('updateTrip error:', err);
      throw err;
    }
  },

  deleteTrip: async (tripId) => {
    try {
      await tripsApi.delete(tripId);
      set({ trip: null, activeDayId: null });
    } catch (err: any) {
      console.error('deleteTrip error:', err);
      throw err;
    }
  },

  addPlaceToDay: async (placeId, dayId, options) => {
    const { trip } = get();
    if (!trip) return;
    
    // Rollback için önceki state'i sakla
    const previousTrip = structuredClone(trip);
    
    try {
      const day = trip.days.find(d => d.id === dayId);
      if (!day) throw new Error('Gün bulunamadı');
      
      // Optimistic: Yer bilgilerini çekip state'i güncelle
      const placeData = await placesApi.getById(placeId);
      if (!placeData) throw new Error('Yer bilgisi alınamadı');
      
      const newTripPlace: TripPlace = {
        id: placeData.id,
        tripPlaceId: `temp-${Date.now()}`,
        name: placeData.name || 'Bilinmeyen Yer',
        type: placeData.type || 'activity',
        duration: placeData.duration || '2 saat',
        img: placeData.image_url,
        position: {
          lat: Number(placeData.latitude || 0),
          lng: Number(placeData.longitude || 0),
        },
        rating: placeData.rating,
        description: placeData.description,
        notes: options?.notes || '',
        timeOfDay: options?.time_block,
        order_index: day.places.length,
      };

      // State'i optimistik olarak güncelle
      set((state) => {
        if (!state.trip) return state;
        return {
          trip: {
            ...state.trip,
            days: state.trip.days.map(d => 
              d.id === dayId 
                ? { ...d, places: [...d.places, newTripPlace] } 
                : d
            )
          }
        };
      });
      
      // API çağrısı
      const createdRecord = await tripPlacesApi.addToDay({
        trip_day_id: dayId,
        place_id: placeId,
        order_index: day.places.length,
        duration: newTripPlace.duration,
        time_block: options?.time_block,
        notes: options?.notes,
      });

      // Geçici ID'yi gerçek ID ile güncelle
      set((state) => {
        if (!state.trip) return state;
        return {
          trip: {
            ...state.trip,
            days: state.trip.days.map(d => ({
              ...d,
              places: d.places.map(p => 
                p.tripPlaceId === newTripPlace.tripPlaceId 
                  ? { ...p, tripPlaceId: createdRecord.id } 
                  : p
              )
            }))
          }
        };
      });

      get().setNewlyAddedPlaceId(createdRecord.id);
    } catch (err: any) {
      console.error('addPlaceToDay error:', err);
      // Hata durumunda geri al
      set({ trip: previousTrip });
      throw err;
    }
  },

  removePlaceFromDay: async (tripPlaceId) => {
    const { trip } = get();
    if (!trip) return;
    
    // Rollback için önceki state'i sakla
    const previousTrip = structuredClone(trip);
    
    try {
      // Optimistik güncelleme
      set((state) => {
        if (!state.trip) return state;
        return {
          trip: {
            ...state.trip,
            days: state.trip.days.map(day => ({
              ...day,
              places: day.places
                .filter(p => p.tripPlaceId !== tripPlaceId)
                .map((p, idx) => ({ ...p, order_index: idx }))
            }))
          }
        };
      });
      
      await tripPlacesApi.remove(tripPlaceId);
    } catch (err: any) {
      console.error('removePlaceFromDay error:', err);
      // Hata durumunda geri al
      set({ trip: previousTrip });
      throw err;
    }
  },

  reorderPlaces: async (dayId, places) => {
    const { trip } = get();
    if (!trip) return;
    
    // Rollback için önceki state'i sakla
    const previousTrip = structuredClone(trip);
    
    try {
      // Optimistik güncelleme
      set((state) => {
        if (!state.trip) return state;
        return {
          trip: {
            ...state.trip,
            days: state.trip.days.map(day => {
              if (day.id === dayId) {
                return {
                  ...day,
                  places: places.map((p, idx) => ({ ...p, order_index: idx }))
                };
              }
              return day;
            })
          }
        };
      });
      
      const updates = places.map((place, index) => ({
        tripPlaceId: place.tripPlaceId,
        orderIndex: index,
      }));

      await tripPlacesApi.updatePlacesOrder(dayId, updates);
    } catch (err: any) {
      console.error('reorderPlaces error:', err);
      set({ trip: previousTrip });
      throw err;
    }
  },

  setHoveredPlaceId: (id) => set({ hoveredPlaceId: id }),
  setSelectedPlaceId: (id) => set({ selectedPlaceId: id }),
  setActiveTab: (tab) => set({ activeTab: tab }),
  setIsAddPlaceOpen: (open) => set({ isAddPlaceOpen: open }),
  setHighlightedPlaceId: (id) => set({ highlightedPlaceId: id }),
  setNewlyAddedPlaceId: (id) => set({ newlyAddedPlaceId: id }),
  setActiveDayId: (dayId) => {
    set({ activeDayId: dayId });
    const { trip } = get();
    if (trip?.id) {
      if (dayId) {
        localStorage.setItem(`trip_active_day_${trip.id}`, dayId);
      } else {
        localStorage.removeItem(`trip_active_day_${trip.id}`);
      }
    }
  },
}));

// Selectors for optimized performance
export const useActiveDay = () => {
  const trip = useTripStore(state => state.trip);
  const activeDayId = useTripStore(state => state.activeDayId);
  if (!trip || !activeDayId) return null;
  return trip.days.find(day => day.id === activeDayId) || null;
};

export const useActiveDayTimelineBlocks = () => {
  const activeDay = useActiveDay();
  if (!activeDay || !activeDay.places.length) return [];
  
  const activeDayPlaces = activeDay.places;
  const timeBlockMap = assignTimeBlocks(activeDayPlaces);
  const blockGroups = new Map<TimeBlock, TripPlace[]>();
  
  activeDayPlaces.forEach(place => {
    const placeKey = place.tripPlaceId || place.id;
    const blockInfo = timeBlockMap.get(placeKey);
    if (blockInfo) {
      const existing = blockGroups.get(blockInfo.timeBlock) || [];
      blockGroups.set(blockInfo.timeBlock, [...existing, { ...place, ...blockInfo }]);
    }
  });
  
  const blocks: TimelineBlock[] = [];
  const blockOrder: TimeBlock[] = ['dawn', 'morning', 'afternoon', 'evening'];
  
  blockOrder.forEach(timeBlock => {
    const places = blockGroups.get(timeBlock);
    if (places && places.length > 0) {
      blocks.push({ timeBlock, places });
    }
  });
  
  return blocks;
};

export const useAllMapMarkers = () => {
  const trip = useTripStore(state => state.trip);
  if (!trip) return [];
  
  const markers: MapMarker[] = [];
  trip.days.forEach((day, dayIndex) => {
    day.places.forEach((place) => {
      markers.push({
        id: place.id,
        lat: place.position.lat,
        lng: place.position.lng,
        dayId: day.id,
        dayIndex,
        orderIndex: place.order_index,
        title: place.name,
      });
    });
  });
  
  return markers;
};

export const useActiveDayMapMarkers = () => {
  const trip = useTripStore(state => state.trip);
  const activeDay = useActiveDay();
  if (!activeDay || !trip) return [];
  
  const dayIndex = trip.days.findIndex(d => d.id === activeDay.id) || 0;
  
  return activeDay.places.map((place) => ({
    id: place.id,
    lat: place.position.lat,
    lng: place.position.lng,
    dayId: activeDay.id,
    dayIndex,
    orderIndex: place.order_index,
    title: place.name,
  }));
};
